void _handler_InsteonTrafficDetected(object sender, InsteonTrafficEventArgs e)
 {
 }
        //public void ParseCommand(byte[] commandBytes)
        //{
        //    //if (commandBytes.Length < 5)
        //    //{
        //    //    log.Error(string.Format("Received command not of sufficient length ({0}), command: {1}", commandBytes.Length, BytesToString(commandBytes)));
        //    //    return;
        //    //}
        //    if (commandBytes[0] != 0x02)
        //    {
        //        log.Error(string.Format("Received Command must start with 0x02.  Received command: {0}", BytesToString(commandBytes)));
        //        return;
        //    }
        //    // determine whether the command is an ack
        //    if (CompareToLastSentCommand(commandBytes))
        //    {
        //        // no need to parse ACK commands
        //        if (commandBytes[_lastSentCommand.Length] == 0x06)
        //        {
        //            if (commandBytes.Length > _lastSentCommand.Length + 1)
        //            {
        //                byte[] remainingBytes = new byte[commandBytes.Length - (_lastSentCommand.Length + 1)];
        //                Buffer.BlockCopy(commandBytes, _lastSentCommand.Length + 1, remainingBytes, 0, remainingBytes.Length);
        //                ParseCommand(remainingBytes);
        //            }
        //            _lastSentCommand = null;
        //            return;
        //        }
        //        else if (commandBytes[_lastSentCommand.Length] == 0x15)
        //        {
        //            log.Warn(string.Format("Received NAK for Command {0}", BytesToString(commandBytes)));
        //            _lastSentCommand = null;
        //            return;
        //        }
        //    }
        //    if (0x50 == commandBytes[1]) // STD message received (11 bytes)
        //    {
        //        if (commandBytes.Length < 11)
        //        {
        //            log.Error(string.Format("Bad standard command received {0}", BytesToString(commandBytes)));
        //            return;
        //        }
        //        byte[] singleCommand = new byte[11];
        //        for (int i = 0; i < 11; i++)
        //        {
        //            singleCommand[i]=commandBytes[i];
        //        }
        //        ProcessStandardReceivedMessage(singleCommand);
        //        if (commandBytes.Length > 11)
        //        {
        //            byte[] remainingBytes = new byte[commandBytes.Length - 11];
        //            Buffer.BlockCopy(commandBytes, 11, remainingBytes, 0, commandBytes.Length - 11);
        //            ParseCommand(remainingBytes);
        //        }
        //    }
        //    else if (0x51 == commandBytes[1]) // EXT message received
        //    {
        //        if (commandBytes.Length < 25)
        //        {
        //            log.Error(string.Format("Bad extended command received {0}", BytesToString(commandBytes)));
        //            return;
        //        }
        //        byte[] singleCommand = new byte[25];
        //        for (int i = 0; i < 25; i++)
        //        {
        //            singleCommand[i]=commandBytes[i];
        //        }
        //    }
        //}
        //public void SetLastCommand(byte[] cmd)
        //{
        //    _lastSentCommand = cmd;
        //}
        private void ProcessStandardReceivedMessage(byte[] message)
        {
            DeviceAddress fromAddress = new DeviceAddress(message[2],message[3],message[4]);
            DeviceAddress toAddress = new DeviceAddress(message[5], message[6], message[7]);

            // check flags for group/device
            byte flagByte = (byte)(message[8] & (byte)0xE0);
            MessageFlag flag = (MessageFlag)flagByte;
            string flagDescription = "unknown";

            switch (flag)
            {
                case MessageFlag.DirectMessage:
                    flagDescription = "Direct Message";
                    break;
                case MessageFlag.ACKDirectMessage:
                    flagDescription = "ACK Direct Message";
                    break;
                case MessageFlag.ACKGroupCleanupDirectMessage:
                    flagDescription = "ACK Group Cleanup DM";
                    break;
                case MessageFlag.BroadcastMessage:
                    flagDescription = "Broadcast Message";
                    break;
                case MessageFlag.GroupBroadcastMessage:
                    flagDescription = "Group Broadcast Message";
                    break;
                case MessageFlag.GroupCleanupDirectMessage:
                    flagDescription = "Group Cleanup DM";
                    break;
                case MessageFlag.NAKDirectMessage:
                    flagDescription = "NAK Direct Message";
                    break;
                case MessageFlag.NAKGroupCleanupDirectMessage:
                    flagDescription = "NAK Group Cleanup DM";
                    break;
                default:
                    break;
            }

            if ((message[8] & 0x10) != 0) // standard message
            {
                log.Error(string.Format("Process Standard Received Message got extended message flag"));
                return;
            }

            int retransmissions = (message[8] & 0x0C) >> 2;

            int maxHops = message[8] & 0x03;

            byte command1 = message[9];
            byte command2=message[10];

            string commandType = "unknown";
            Device sourceDevice = FindDeviceForAddress(fromAddress.ToString());
            Device targetDevice = FindDeviceForAddress(toAddress.ToString());
            if (null != targetDevice && targetDevice is PLMDevice)
            {
                if (_gettingStatus)
                {
                    byte delta = 0x00;
                    //if (_gettingOpFlags)
                    //{
                    //    delta = message[10];
                    //    sourceDevice.Delta = delta;
                    //    log.InfoFormat("Attempting to read database delta from ops flags, result: {0}", delta);
                    //}
                    //else
                    //{
                        // read the command2 and 1 of the response to get the level as well

                    byte level = message[10];
                    delta = message[9];

                    sourceDevice.Status = ((int)level / 255m) * 100m;
                    sourceDevice.Delta = delta;

                    //}
                    _statusEventWaitHandle.Set();
                }
                else if (sourceDevice is ThermostatDevice)
                {
                    if (_gettingThermostat)
                    {
                        if (command1 == 0x6A)
                        {
                            if (_gettingTemp)
                            {
                                ((ThermostatDevice)sourceDevice).AmbientTemperature = (int)Math.Round(((decimal)command2) / 2m,0);
                                _gettingTemp = false;
                            }
                            else if (_gettingSetPoint)
                            {
                                if (((ThermostatDevice)sourceDevice).CurrentMode == ThermostatDevice.Mode.Cooling)
                                    ((ThermostatDevice)sourceDevice).CoolSetPoint = (int)Math.Round(((decimal)command2) / 2m, 0);
                                else
                                    ((ThermostatDevice)sourceDevice).HeatSetPoint = (int)Math.Round(((decimal)command2) / 2m, 0);

                                _gettingSetPoint = false;

                            }
                            else if (_gettingHumidity)
                            {
                                ((ThermostatDevice)sourceDevice).Humidity = (int)command2;

                                _gettingHumidity = false;

                            }
                            else
                                log.WarnFormat("Received thermostat update {0} and unsure of what we requested.", command2.ToString("X"));

                            _statusEventWaitHandle.Set();

                        }
                        return;
                    }

                    ThermostatDevice thermostat = sourceDevice as ThermostatDevice;

                    switch (command1)
                    {
                        case Constants.STD_COMMAND_THERMOSTAT_STATUS_TEMP:
                            thermostat.AmbientTemperature = (int)Math.Round(((decimal)command2) * 0.5m, 0);

                            log.InfoFormat("Received temperature update: {0}", thermostat.AmbientTemperature);
                            SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(thermostat.Name,
                                string.Format("Temperature detected: {0}°F", thermostat.AmbientTemperature)));

                            break;
                        case Constants.STD_COMMAND_THERMOSTAT_STATUS_HUMIDITY:
                            thermostat.Humidity = (int)command2;
                            log.InfoFormat("Received humidity update: {0}", thermostat.Humidity);

                            break;
                        case Constants.STD_COMMAND_THERMOSTAT_STATUS_MODE_FAN:
                            log.InfoFormat("Thermostat mode byte: {0}", command2.ToString("X"));
                            // extract mode, low byte 0=off,1=heat,2=cool,3=auto,4=program
                            if ((command2 & 0x0F) == 0x00)
                                thermostat.CurrentMode = ThermostatDevice.Mode.Off;
                            else if ((command2 & 0x0F) == 0x01)
                                thermostat.CurrentMode = ThermostatDevice.Mode.Heating;
                            else if ((command2 & 0x0F) == 0x02)
                                thermostat.CurrentMode = ThermostatDevice.Mode.Cooling;
                            else if ((command2 & 0x0F) == 0x03)
                                thermostat.CurrentMode = ThermostatDevice.Mode.Auto;
                            else if ((command2 & 0x0F) == 0x04)
                                thermostat.CurrentMode = ThermostatDevice.Mode.Program;
                            else
                                log.WarnFormat("Unable to determine mode from status byte: {0}", command2.ToString("X"));

                            // extract fan info, high byte command 2, 0=auto,1=alwayson
                            if ((command2 & 0xF0) == 0x00)
                                thermostat.Fan = ThermostatDevice.FanMode.Auto;
                            else if ((command2 & 0xF0) == 0x10)
                                thermostat.Fan = ThermostatDevice.FanMode.AlwaysOn;
                            else
                                log.WarnFormat("Unable to determine fan from status byte: {0}", command2.ToString("X"));

                            SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(thermostat.Name,
                                string.Format("Mode: {0}, Fan: {1}", thermostat.CurrentMode, thermostat.Fan)));
                            break;
                        case Constants.STD_COMMAND_THERMOSTAT_STATUS_COOL_SET:
                            thermostat.CoolSetPoint = (int)(command2);
                            log.InfoFormat("Received thermostat cool setpoint update: {0}", thermostat.CoolSetPoint);

                            SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(thermostat.Name,
                                string.Format("Cool set point: {0}", thermostat.CoolSetPoint)));

                            break;
                        case Constants.STD_COMMAND_THERMOSTAT_STATUS_HEAT_SET:
                            thermostat.HeatSetPoint = (int)(command2);
                            log.InfoFormat("Received thermostat heat setpoint update: {0}", thermostat.HeatSetPoint);
                            SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(thermostat.Name,
                                string.Format("Heat set point: {0}", thermostat.HeatSetPoint)));
                            break;
                        default:
                            log.InfoFormat("Unknown message from thermostat device received: {0}", command1.ToString("X"));
                            break;
                    }
                }

                // this is received before the ALDB comes, its part of a sequence of extended messages
                // but 0x2F as a standard message is LightOffAtRampRate
                if (command1 == 0x2F)
                {
                    log.Info(string.Format("Received Message from {0} to {1} of type: ({2}):{3} ({4})", GetDeviceName(fromAddress.ToString()), GetDeviceName(toAddress.ToString()), command1.ToString("X"), command2.ToString("X"), flagDescription));
                    log.Info("Beginning of ALDB records.");
                    return;
                } // same as above but for reading device info
                else if (command1 == 0x2E)
                {
                    log.Info(string.Format("Received Message from {0} to {1} of type: ({2}):{3} ({4})", GetDeviceName(fromAddress.ToString()), GetDeviceName(toAddress.ToString()), command1.ToString("X"), command2.ToString("X"), flagDescription));
                    log.Info("Beginning of Extended Read");
                    return;
                }
            }

            switch (command1)
            {
                case Constants.STD_COMMAND_BEEP:
                    break;
                case Constants.STD_COMMAND_BRIGHT:
                    break;
                case Constants.STD_COMMAND_DIM:
                    commandType = "Dim";
                    break;
                case Constants.STD_COMMAND_FAST_OFF:
                    if (null != sourceDevice && (flag & MessageFlag.ACKDirectMessage) == 0)
                    {
                        if ((null != targetDevice && targetDevice is PLMDevice) || toAddress.Byte3 == 0x01)
                        {
                            sourceDevice.Status = 0;
                            sourceDevice.LastOff = DateTime.Now;
                            SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(sourceDevice.Name,
                                string.Format("Fast off by keypress.")));
                        }
                    }

                    commandType = "FastOff";
                    break;
                case Constants.STD_COMMAND_FAST_ON:
                    if (null != sourceDevice && (flag & MessageFlag.ACKDirectMessage) == 0)
                    {
                        if ((null != targetDevice && targetDevice is PLMDevice) || toAddress.Byte3 == 0x01)
                        {
                            sourceDevice.LastOn = DateTime.Now;
                            if (sourceDevice is DimmerDevice)
                                sourceDevice.Status = (command2 * 100) / 0xFF;
                            else
                                sourceDevice.Status = 100;
                            SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(sourceDevice.Name,
                                string.Format("Fast on by keypress.")));
                        }
                    }

                    // setting a timer on an ack message is redundant
                    if (sourceDevice.DefaultOffMinutes.HasValue && ((flag & MessageFlag.ACKDirectMessage) != MessageFlag.ACKDirectMessage))
                    {
                        log.DebugFormat("Setting default off timer for device: {0} minutes.", sourceDevice.DefaultOffMinutes.Value);
                        sourceDevice.SetTimer(new Devices.DeviceTimerCallBack(DeviceTimerCallBack));
                    }

                    commandType = "FastOn";
                    break;
                case Constants.STD_COMMAND_GET_OP_FLAGS:
                    break;
                case Constants.STD_COMMAND_LIGHT_INSTANT_CHANGE:
                    break;
                case Constants.STD_COMMAND_LIGHT_MANUAL_OFF:
                    commandType = "LightManualOff";
                    break;
                case Constants.STD_COMMAND_LIGHT_MANUAL_ON:
                    commandType = "LightManualOn";
                    break;
                case Constants.STD_COMMAND_LIGHT_RAMP_OFF:
                    if (null != sourceDevice && (flag & MessageFlag.ACKDirectMessage) == 0)
                    {
                        if ((null != targetDevice && targetDevice is PLMDevice) || toAddress.Byte3 == 0x01)
                        {
                            sourceDevice.Status = 0;
                            sourceDevice.LastOff = DateTime.Now;
                        }
                    }

                    commandType = "LightRampOff";
                    break;
                case Constants.STD_COMMAND_LIGHT_RAMP_ON:
                    if (null != sourceDevice && (flag & MessageFlag.ACKDirectMessage) == 0)
                    {
                        if ((null != targetDevice && targetDevice is PLMDevice) || toAddress.Byte3 == 0x01)
                        {
                            sourceDevice.LastOn = DateTime.Now;
                            if (sourceDevice is DimmerDevice)
                                sourceDevice.Status = (command2 * 100) / 0xFF;
                            else
                                sourceDevice.Status = 100;
                        }
                    }

                    if (sourceDevice.DefaultOffMinutes.HasValue)
                    {
                        log.DebugFormat("Setting default off timer for device: {0} minutes.", sourceDevice.DefaultOffMinutes.Value);
                        sourceDevice.SetTimer(new DeviceTimerCallBack(DeviceTimerCallBack));
                    }

                    commandType = "LightRampOn";
                    break;

                case Constants.STD_COMMAND_LIGHT_SET_STATUS:
                    commandType = "LightSetStatus";
                    break;

                case Constants.STD_COMMAND_OFF:
                    if (null != sourceDevice && (flag & MessageFlag.ACKDirectMessage) == 0)
                    {
                        if ((null != targetDevice && targetDevice is PLMDevice) || toAddress.Byte3 == 0x01)
                        {
                            sourceDevice.Status = 0;
                            sourceDevice.LastOff = DateTime.Now;

                            if (!(sourceDevice is ThermostatDevice))
                            {
                                SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(sourceDevice.Name,
                                      string.Format("Turned off by keypress.")));
                            }
                        }
                    }
                    commandType = "CommandOff";
                    break;
                case Constants.STD_COMMAND_ON:

                    if (null != sourceDevice && (flag & MessageFlag.ACKDirectMessage) == 0)
                    {
                        if ((null != targetDevice && targetDevice is PLMDevice) || toAddress.Byte3 == 0x01)
                        {
                            sourceDevice.LastOn = DateTime.Now;
                            if (sourceDevice is DimmerDevice)
                                sourceDevice.Status = (command2 * 100) / 0xFF;
                            else if (sourceDevice is SensorDevice)
                                sourceDevice.Status = 0;// dont actually turn on
                            else
                                sourceDevice.Status = 100;

                            if (!(sourceDevice is ThermostatDevice))
                            {
                                if (sourceDevice is SensorDevice)
                                    SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(sourceDevice.Name,
                                        string.Format("Motion Detected")));
                                else
                                    SlapsteonEventLog.AddLogEntry(new SlapsteonEventLogEntry(sourceDevice.Name,
                                        string.Format("Turned on by keypress.")));
                            }
                        }
                    }

                    if (sourceDevice.DefaultOffMinutes.HasValue)
                    {
                        log.DebugFormat("Setting default off timer for device: {0} minutes.", sourceDevice.DefaultOffMinutes.Value);
                        sourceDevice.SetTimer(new DeviceTimerCallBack(DeviceTimerCallBack));
                    }

                    if (sourceDevice.Name == "zone1IOLinc")
                    {
                        if (null != PartyDetected)
                        {
                            PartyDetected(this);
                        }
                    }

                    commandType = "CommandOn";
                    break;
                case Constants.STD_COMMAND_REMOTE_SET_BUTTON_TAP:
                    break;
                case Constants.STD_COMMAND_SET_OP_FLAGS:
                    break;
                case Constants.STD_COMMAND_START_MANUAL:
                    commandType = "StartManual";
                    break;
                case Constants.STD_COMMAND_STATUS_REQUEST:
                    break;
                case Constants.STD_COMMAND_STOP_MANUAL:
                    commandType = "StopManual";
                    break;
                default:
                    break;
            }

            ProcessRelatedDeviceEvents(command1, command2, fromAddress, toAddress);

            log.Info(string.Format("Received Message from {0} to {1} of type: {2}({3}):{4} ({5})", GetDeviceName(fromAddress.ToString()), GetDeviceName(toAddress.ToString()), commandType, command1.ToString("X"), command2.ToString("X"), flagDescription));

            if (null != InsteonTrafficDetected)
            {
                InsteonTrafficEventArgs args = new InsteonTrafficEventArgs();
                args.Source = _allDevices.ContainsKey(fromAddress.ToString()) ? _allDevices[fromAddress.ToString()] : null;
                args.Destination = toAddress;
                args.Flags = flag;
                args.Command1 = command1;
                args.Command2 = command2;
                args.Description = string.Format("Command={0}/DestName={1}", commandType, GetDeviceName(toAddress.ToString()));
                InsteonTrafficDetected(this, args);
            }
        }
Example #3
0
 public void InsteonTrafficDetected(object sender, InsteonTrafficEventArgs e)
 {
     this.InsertConsoleText(e.ToString() + Environment.NewLine);
 }