-----------------------
    Common parameters/types
    -----------------------
    BYTE [1 byte]

    CMD_ID [1 byte]
        Command IDs:
        0  - CMD_ID_REBOOT
        1  - CMD_ID_DB_SAVE
        2  - CMD_ID_TEMP_OUTPUT_ENABLE
        3  - CMD_ID_SERVICES
        4  - CMD_ID_SET_MANUAL_MODE
        5  - CMD_ID_DUMP_ALL
        6  - CMD_ID_NAME_CHANGE
        7  - CMD_ID_ALARM_MODE
        8  - CMD_ID_TEMP_CHANGE
        9  - CMD_ID_SWITCH_CHANGE
        10 - CMD_ID_VERSION
        11 - CMD_ID_GET_ERROR_CODE
        12 - CMD_ID_PING
        13 - CMD_ID_SWITCH_ENABLE
        14 - CMD_ID_HTTP_PORT
        15 - CMD_ID_DUTY_CYCLE_MIN_MAX
        16 - CMD_ID_DUTY_CYCLE_TIME_SLICE

    OW_ID [8 bytes]
        BYTE
            id_07_00
        BYTE
            id_15_08
        BYTE
            id_23_16
        BYTE
            id_31_24
        BYTE
            id_39_32
        BYTE
            id_47_40
        BYTE
            id_55_48
        BYTE
            id_63_56

            Dallas Semiconductor 64-bit OneWire ID

    OW_ID_NULL [8 bytes]
        BYTE
            0
        BYTE
            0
        BYTE
            0
        BYTE
            0
        BYTE
            0
        BYTE
            0
        BYTE
            0
        BYTE
            0

            NULL ID

    STRING [variable size]
        0...x
        '\0'
            ASCII chars followed by null termination

    BOOL [1 byte]
        0 - false
        1 - true

    SHORT [2 bytes]
        BYTE
            val_07_00
        BYTE
            val_15_08

    ALARM_MODE [1 byte]
        0 - NONE
        1 - Target
        2 - Hi/lo window

    TEMP_ID [1 byte]
        0 - Target
        1 - Alarm window lo
        2 - Alarm window hi

    TEMP_VAL [4 bytes]
        BYTE
            temp_07_00
        BYTE
            temp_15_08
        BYTE
            temp_23_16
        BYTE
            temp_31_24

            This will be a fixed point number.  The signed integer part will be located
            in bits 31-03.  The bits 2-0 will be the fractional part.

    COMPONENT_TYPE [1 byte]
        0 - COMPONENT_SENSOR
        1 - COMPONENT_SWITCH

    INFO_SENSOR [(37 + null terminated string) bytes]
        OW_ID
        COMPONENT_TYPE
            Force to COMPONENT_SENSOR
        SHORT
            string length including NULL termination
        STRING
            User-defined name
        OW_ID|OW_ID_NULL
            ID of associated switch
        ALARM_MODE
        TEMP_VAL
            alarm hi
        TEMP_VAL
            alarm lo
        TEMP_VAL
            target
        TEMP_VAL
            current temperature
        BYTE
            status byte
            0:0
                0 = manual mode off
                1 = manual mode on

    INFO_SWITCH [(24 + null terminated string) bytes]
        OW_ID
        COMPONENT_TYPE
            Force to COMPONENT_SWITCH
        SHORT
            string length including NULL termination
        STRING
        OW_ID|OW_ID_NULL
            ID of associated sensor
        BYTE
            7:7 - switch on/off state (1 is on)
            6:0 - blower duty cycle [100 - 0] (0 if no blower)
        SHORT
            time slice multiplier
        BYTE
            min duty cycle
        BYTE
            max duty cycle

    VERSION_NUMBER [4 bytes]
        BYTE
            build
        BYTE
            release
        BYTE
            minor
        BYTE
            major

    CMD_RET [1 byte]
        0 - CMD_RET_SUCCESS
        1 - CMD_RET_ERROR


    ----------------------------------------
    Individual commands and their parameters
    ----------------------------------------
    COMMAND_HEADER [7 bytes]
        SHORT
            0x3333 (command signature)
        SHORT
            command serial number
        SHORT
            payload size
        BYTE
            checksum

            The checksum is calculated over the entire
            command except the checksum field.  This means
            the first 6 bytes of the header plus the
            entire payload will be used to calculate
            the checksum.

            Payload is command id field as well as
            any fields after the command id.

    All the indented fields are the command's mandatory parameters.
    If a command does not have any indented fields, then the command
    has no parameters.

    CMD_REBOOT [8 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_REBOOT

    CMD_DB_SAVE [8 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_DB_SAVE

    CMD_TEMP_OUTPUT_ENABLE [10 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_TEMP_OUTPUT_ENABLE
        SHORT
            port number

    CMD_SERVICES [9 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_SERVICES
        BOOLEAN
            0 - disable other services
            1 - enable services

        The specific "services" shutdown/enabled are the front
        panel keyboard and the web server.  So, if the services
        are disabled, both the keypad and the web interface will
        cease to respond.

        Even if the services are disabled, the Stoker will attempt
        to re-enable them once the socket connection is broken.

    CMD_DUMP_ALL [8 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_DUMP_ALL

    CMD_NAME_CHANGE [(18 + null terminated string) bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_NAME_CHANGE
        OW_ID
        SHORT
            string length including NULL termination
        STRING
            new name for device

    CMD_ALARM_MODE [17 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_ALARM_MODE
        OW_ID
        ALARM_MODE

    CMD_TEMP_CHANGE [21 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_TEMP_CHANGE
        OW_ID
        TEMP_ID
        TEMP_VAL

    CMD_SWITCH_CHANGE [24 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_SWITCH_CHANGE
        OW_ID
            Sensor ID
        OW_ID|OW_ID_NULL
            Switch ID

    CMD_VERSION [8 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_VERSION

    CMD_GET_ERROR_CODE [8 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_GET_ERROR_CODE

    CMD_PING [8 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_PING

    CMD_SWITCH_ENABLE [17 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_SWITCH_ENABLE
        OW_ID
            Switch ID
        BOOLEAN
            0 - switch off
            1 - switch on

        Limitations: CMD_SWITCH_ENABLE is valid only when
        the Stoker is in manual mode.

    CMD_SET_MANUAL_MODE [9 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_SET_MANUAL_MODE
        BOOLEAN
            0 - disable manual mode.  This means enabling
                the control functionality within the stoker
            1 - enable manual mocde.  This means the client
                will have direct control over the fan.

    CMD_HTTP_PORT [10 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_HTTP_PORT
        SHORT
            New port number for the HTTP server

    CMD_DUTY_CYCLE_MIN_MAX [18 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_DUTY_CYCLE_MIN_MAX
        OW_ID
            Switch ID
        BYTE
            minimum duty cycle percentage [range: 0 - 100]
        BYTE
            maximum duty cycle percentage [range: 0 - 100]

            Both the min and max will be rounded to the
            nearest 10%.

    CMD_DUTY_CYCLE_TIME_SLICE [18 bytes]
        CMD_HEADER
        CMD_ID
            CMD_ID_DUTY_CYCLE_TIME_SLICE
        OW_ID
            Switch ID
        SHORT
            multiplier on the time slice.

            Background:
            "Time slice" in this context is the length of time between
            each update of the devices in the system.

            Switches implement their duty cycle by updating their
            on and off status during every time slice.  Switches
            implement duty cycle with a resolution of 10%.  This means
            the actual duty cycle is either 0, 10, 20, 30, 40, 50, 60,
            70, 80, 90, or 100%.

            In general, the default time slice is roughly one second.

            So, as an example, assume a switch is running at 40% duty
            cycle.  And assume the time slice is one second.  This means
            the switch will be on for 4 time slices (4 seconds) and off
            for 6 time slices (6 seconds).

            What does this command do?:
            In some applications, the resolution on the order of one
            second is too short.  Some application require the switch
            to be on for a minumum of x seconds.

            To implement this minumum, the command allows the
            application to determine a multipler for the default time
            slice.

            So, assume the default time slice is one second.  And
            assume the application requires that the switch be active
            for a minimum of 30 seconds.

            In this example, the multipler should be set to 30 so that
            each time slice is (1 second) x 30 = 30 seconds.  So even at
            10% duty cycle (1 time slice on, 9 time slices off), the
            switch will be on for at least 30 seconds.


    ----------------------------------------
    Individual responses
    ----------------------------------------
    RESPONSE_HEADER [7 bytes]
        SHORT
            0x4444 (response signature)
        SHORT
            command serial number
        SHORT
            payload size
        BYTE
            checksum

            The checksum is calculated over the entire
            response except the checksum field.  This means
            the first 6 bytes of the header plus the
            entire payload will be used to calculate
            the checksum.

            Payload is everything after the header
            upto and including the CMD_RET field.

    Most responses are the generic responses:

    RESPONSE_GENERIC [8 bytes]
        RESPONSE_HEADER
        CMD_RET
            The return status of the command

    Right now, there are only two responses that differ from the generic.

    RESPONSE_DUMP_ALL [16 bytes minimum + all info structures]
        RESPONSE_HEADER
        [INFO_SENSOR|INFO_SWITCH]*
            Zero or more info structures
        OW_ID_NULL
            Indicator for the end of the list of info structures
        CMD_RET

    RESPONSE_VERSION [16 bytes]
        RESPONSE_HEADER
        VERSION_NUMBER
            socket protocol version
        VERSION_NUMBER
            Stoker firmware version
        CMD_RET

    RESPONSE_GET_ERROR_CODE [(12 + null terminated string) bytes]
        RESPONSE_HEADER
        SHORT
            error code
        SHORT
            string length including NULL termination
        STRING
            detailed error message
        CMD_RET

    ---------------
    Basic structure
    ---------------
    COMMAND_STREAM_HEADER [7 bytes]
        SHORT
            0x2222 (header signature)
        SHORT
            number of commands
        SHORT
            payload size
        BYTE
            checksum

    COMMAND_STREAM
        COMMAND_STREAM_HEADER
        [
            COMMAND_*
        ]+

        The command stream is the object that is sent from the
        client to the Stoker.  The stream consists of a header
        and one or more commands.

        In response, the Stoker will send a response stream.

    RESPONSE_STREAM
        [
            RESPONSE_*
            response-specific parameters
        ]+

        This object is returned by the Stoker to the client.
        This contains one or more response objects.  The
        number of response objects is the same as the number
        of commands.  The order of the responses is also
        maintained so that the first response is associated
        with the first command.


    ----------------------------------------
    Limitations
    ----------------------------------------
    Assume the command stream contains a series of setting changes, and
    at the end of the stream a CMD_ID_DUMP_ALL is used to check
    if the settings have been applied.  This is not guaranteed to work.
    The best way to check the changes is to start another command stream
    with just the CMD_ID_DUMP_ALL.

    When applying setting changes, the changes are not commited to the
    database immediately.  CMD_ID_DB_SAVE must be sent if the
    settings needs to be persistent.

    Although CMD_ID_GET_ERROR_CODE is implemented, it does not
    provide any useful information.  This will be fixed soon.

    The Stoker does not provide a very elegant recovery mechanism.
    Basically, if it finds an error in the stream (like the signature is
    not correct), then it will close the socket.  After a little
    bit of time recovering, the Stoker will start listening on the socket
    again.

    CRCs are not checked and are not generated.  Please ignore those
    fields for right now.