Click here to Skip to main content
15,896,201 members
Articles / Programming Languages / C#

Robot Alarm Clock

Rate me:
Please Sign up or sign in to vote.
4.96/5 (9 votes)
15 Sep 2013CPOL10 min read 27.3K   2.8K   14  
Bluetooth robotic alarm clock using C#
using System.Runtime.InteropServices;

namespace SpheroAlarmClock
{
	public class CommandPacket
	{
		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public class CommandPacketData
		{
			public byte SOP1;
			public byte SOP2;
			public byte DID;
			public byte CID;
			public byte Seq;		// echoed by client in response packet
			public byte Dlen;
			public byte Chk;
		}

		public CommandPacketData pkt;

		public CommandPacket()
		{
			pkt = new CommandPacketData();
			pkt.SOP1 = 0xff;
			pkt.SOP2 = 0xff;
			pkt.Dlen = 0x01;		// always 1 because of the Chksum field
		}

		public byte GetChecksum()
		{
			return (byte)(~((pkt.DID + pkt.CID + pkt.Seq + pkt.Dlen) % 256));
		}

        public byte[] CreateDataStream()
        {
            return Form1.StructureToByteArray(pkt);
        }
	}

	public class SetOptionFlagsPacket
	{
		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public class SetOptionFlagsPacketData
		{
			public byte SOP1;
			public byte SOP2;
			public byte DID;
			public byte CID;
			public byte Seq;		// echoed by client in response packet
			public byte Dlen;
			public byte flagByteMSB;	// highest byte of 32 bits of flags (31-24)
			public byte flagByteLMSB;	// next highest byte of 32 bits of flags (23-16)
			public byte flagByteMLSB;	// next highest byte of 32 bits of flags (15-8)
			public byte flagByteLSB;	// lowest byte of 32 bits of flags (7-0)
			public byte Chk;
		}

		public SetOptionFlagsPacketData pkt;

		public SetOptionFlagsPacket()
		{
			pkt = new SetOptionFlagsPacketData();
			pkt.SOP1 = 0xff;
			pkt.SOP2 = 0xff;
			pkt.Dlen = 5;		// one data byte, one checksum byte
		}

		public byte GetChecksum()
		{
			return (byte)(~((pkt.DID + pkt.CID + pkt.Seq + pkt.Dlen + pkt.flagByteMSB + pkt.flagByteLMSB + pkt.flagByteMLSB + pkt.flagByteLSB) % 256));
		}

		public byte[] CreateDataStream()
		{
			return Form1.StructureToByteArray(pkt);
		}
	}

	public class SetRawMotorPacket
	{
		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public class SetRawMotorPacketData
		{
			public byte SOP1;
			public byte SOP2;
			public byte DID;
			public byte CID;
			public byte Seq;		// echoed by client in response packet
			public byte Dlen;
			public byte LMode;	// left motor mode
			public byte LPower;	// left motor power
			public byte RMode;	// right motor mode
			public byte RPower;	// right motor powe
			public byte Chk;
		}

		public SetRawMotorPacketData pkt;

		public SetRawMotorPacket()
		{
			pkt = new SetRawMotorPacketData();
			pkt.SOP1 = 0xff;
			pkt.SOP2 = 0xff;
			pkt.Dlen = 5;		// one data byte, one checksum byte
		}

		public byte GetChecksum()
		{
			return (byte)(~((pkt.DID + pkt.CID + pkt.Seq + pkt.Dlen + pkt.LMode + pkt.LPower + pkt.RMode + pkt.RPower) % 256));
		}

		public byte[] CreateDataStream()
		{
			return Form1.StructureToByteArray(pkt);
		}
	}

	public class SetRGBLEDPacket
	{
		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public class SetRGBLEDPacketData
		{
			public byte SOP1;
			public byte SOP2;
			public byte DID;
			public byte CID;
			public byte Seq;		// echoed by client in response packet
			public byte Dlen;
			public byte Red;	
			public byte Green;
			public byte Blue;
			public byte flag;
			public byte Chk;
		}

		public SetRGBLEDPacketData pkt;

		public SetRGBLEDPacket()
		{
			pkt = new SetRGBLEDPacketData();
			pkt.SOP1 = 0xff;
			pkt.SOP2 = 0xff;
			pkt.Dlen = 5;		// one data byte, one checksum byte
		}

		public byte GetChecksum()
		{
			return (byte)(~((pkt.DID + pkt.CID + pkt.Seq + pkt.Dlen + pkt.Red + pkt.Green + pkt.Blue + pkt.flag) % 256));
		}

		public byte[] CreateDataStream()
		{
			return Form1.StructureToByteArray(pkt);
		}
	}

    public class ResponsePacket
	{
		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public class Packet
		{
			public byte SOP1;
			public byte SOP2;
			public byte Mrsp;		// response from client
			public byte Seq;		// echoed from command packet
			public byte Dlen;		// length of data section
            public byte[] buf = new byte[0xFF];  // buffer for data section
			public byte Chk;
            public byte CalcChkSum; // Calculated checksum
            public bool ChksumError; // Set to true if the checksum does not match
		}

		//public int Size;
		public Packet pkt;

		public ResponsePacket()
		{
			pkt = new Packet();

			pkt.SOP1 = 0xff;
			pkt.SOP2 = 0xff;
			pkt.Dlen = 1;
			//Size = 6;
		}

        public void MoveDataReceivedToResponsePacket(byte[] dataReceived)
        {
            byte dataCounter = 0;
            int totalNumOfBytes = 0;

            pkt.SOP1 = dataReceived[totalNumOfBytes++];
            pkt.SOP2 = dataReceived[totalNumOfBytes++];
            pkt.Mrsp = dataReceived[totalNumOfBytes++];
            pkt.Seq = dataReceived[totalNumOfBytes++];
            pkt.Dlen = dataReceived[totalNumOfBytes++];
            while (dataCounter < (pkt.Dlen - 1))  // Subtract 1 from data length for checksum byte
            {
                pkt.buf[dataCounter] = dataReceived[totalNumOfBytes++];
                dataCounter++;
            }
            pkt.Chk = dataReceived[totalNumOfBytes];

            pkt.CalcChkSum = 0;    // Intialize to 0
            for (int i = 2; i < totalNumOfBytes; i++)  // calculate the checksum not including SOP1 and SOP2 and checksum byte
                pkt.CalcChkSum += dataReceived[i];    
            pkt.CalcChkSum = (byte)(~pkt.CalcChkSum);
            pkt.ChksumError = (!(pkt.CalcChkSum == pkt.Chk));     // Set error result equal to result of comparison between calculated and received checksum
        }
	}

	enum MessageResponseCodes
	{
		ORBOTIX_RSP_CODE_OK = 0,				// command succedded
		ORBOTIX_RSP_CODE_EGEN,					// general, non-specific error
		ORBOTIX_RSP_CODE_ECHKSUM,				// command check sum failed
		ORBOTIX_RSP_CODE_EFRAG,					// received command fragment
		ORBOTIX_RSP_CODE_EBAD_CMD,				// unknown command id
		ORBOTIX_RSP_CODE_EUNSUPP,				// command currently unsupported
		ORBOTIX_RSP_CODE_EBAD_MSG,				// bad message format
		ORBOTIX_RSP_CODE_EPARAM,				// parameter 
		ORBOTIX_RSP_CODE_EEXEC,					// failed to execute command
	};

    public enum ResponseResults
    {
        GOOD = 1,
        TIMEOUT,
        BAD_CODE
    };
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Unknown
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions