private IList<Wire> GetWires(IEnumerable<XElement> elements, Node node, BusController bus) { var wires = new List<Wire>(); foreach (var xwire in elements) { var input = xwire.Attribute("input").Value; var pin = node.Pins.FirstOrDefault(p => p.Name == input); if (pin == null) throw new WireException("Input pin not found"); var index = Convert.ToByte(xwire.Attribute("index").Value); var address = xwire.Attribute("address") != null && !string.IsNullOrEmpty(xwire.Attribute("address").Value) ? Address.Parse(Convert.ToUInt32(xwire.Attribute("address").Value)) : Address.Empty; var useInputData = xwire.Attribute("useInputData") != null && !string.IsNullOrEmpty(xwire.Attribute("useInputData").Value) && Convert.ToBoolean(xwire.Attribute("useInputData").Value); var cmdText = xwire.Attribute("command").Value.ToUpperInvariant(); byte cmd = 0; #region parse command name switch (cmdText) { case "PING": cmd = NodeCommands.CMD_PING; break; case "RESET": cmd = NodeCommands.CMD_RESET; break; case "READ_CONFIG": cmd = NodeCommands.CMD_READ_CONFIG; break; case "START": cmd = NodeCommands.CMD_START; break; case "STOP": cmd = NodeCommands.CMD_STOP; break; //Pins case "CHANGE_DIGITAL": cmd = NodeCommands.CMD_CHANGE_DIGITAL; break; case "TOGGLE_DIGITAL": cmd = NodeCommands.CMD_TOGGLE_DIGITAL; break; case "TIMED_DIGITAL": cmd = NodeCommands.CMD_TIMED_DIGITAL; break; case "DELAY_DIGITAL": cmd = NodeCommands.CMD_DELAY_DIGITAL; break; case "PULSE_DIGITAL": cmd = NodeCommands.CMD_PULSE_DIGITAL; break; case "CYCLE_DIGITAL": cmd = NodeCommands.CMD_CYCLE_DIGITAL; break; case "CHANGE_ALL_DIGITAL": cmd = NodeCommands.CMD_CHANGE_ALL_DIGITAL; break; case "CHANGE_PWM": cmd = NodeCommands.CMD_CHANGE_PWM; break; case "CHANGE_PIN": cmd = NodeCommands.CMD_CHANGE_PIN; break; case "DELAY_TOGGLE_DIGITAL": cmd = NodeCommands.CMD_DELAY_TOGGLE_DIGITAL; break; case "DELTA_PWM": cmd = NodeCommands.CMD_DELTA_PWM; break; case "FADE_PWM": cmd = NodeCommands.CMD_FADE_PWM; break; case "ACTIVATE": cmd = NodeCommands.CMD_ACTIVATE; break; case "DEACTIVATE": cmd = NodeCommands.CMD_DEACTIVATE; break; case "EXECUTE_DEVICE_ACTION": cmd = NodeCommands.CMD_EXECUTE_DEVICE_ACTION; break; case "PUSH_SENSOR_READ": cmd = NodeCommands.CMD_READ_SENSOR; break; } #endregion var dataText = xwire.Attribute("data") != null ? xwire.Attribute("data").Value : string.Empty; var data = Csv.CsvToList<byte>(dataText).ToArray(); //var trgText = xwire.Attribute("trigger") != null ? xwire.Attribute("trigger").Value : string.Empty; //var trgs = Csv.CsvToList<string>(trgText).ToArray(); //var trigger = WireTriggers.None; //foreach (var trg in trgs) //{ // trigger |= trg != null && Enum.IsDefined(typeof (WireTriggers), trg) // ? (WireTriggers) Enum.Parse(typeof (WireTriggers), trg) // : WireTriggers.None; //} var wire = new Wire(pin) { Index = index, Command = cmd, Address = address, UseInputData = useInputData, Parameters = data }; //Add wire trigger event //TODO configurable on Activate/deactivate/change wire.OnWireTriggered += (sender, args) => { var w = (Wire)sender; var stack = new SimpleStack(w.Parameters); if (w.UseInputData) { stack.Push(args.Source.Value); } if (w.Address == Address.Empty || w.Address == bus.Address) node.Execute(w.Address, w.Command, stack.Data); else bus.SendImmediate(w.Command, w.Address, stack.Data); }; wires.Add(wire); } Log.Debug(string.Format("Configured {0} wires", wires.Count)); return wires; }
/// <summary> /// Execute node command /// </summary> /// <param name="source">Source of command</param> /// <param name="command">HBus command</param> /// <param name="datain">Command data</param> /// <returns>true if command is executed</returns> public bool Execute(Address source, byte command, byte[] datain) { try { byte index; int value; byte delay; byte width; string name; Pin pin; Sensor sensor; Device device; var stack = new SimpleStack(datain); var dataOut = new List<byte>(); var done = false; switch (command) { #region Bus commands case NodeCommands.CMD_PING: dataOut.AddRange(FixedString.ToArray(Name, HBusSettings.NameLength)); _bus.Payload = dataOut.ToArray(); done = true; break; #endregion #region Node commands case NodeCommands.CMD_RESET: index = stack.PopByte(); //1 = full reset Reset(index == 1); done = true; break; case NodeCommands.CMD_START: Start(); done = true; break; case NodeCommands.CMD_STOP: Stop(); done = true; break; case NodeCommands.CMD_FACTORY_DEFAULT: LoadConfiguration(true); done = true; break; case NodeCommands.CMD_READ_CONFIG: LoadConfiguration(false); done = true; break; case NodeCommands.CMD_WRITE_CONFIG: SaveConfiguration(); done = true; break; case NodeCommands.CMD_ADD_NODE_LISTENER: //index = stack.PopByte(); //mask //Add pin to subscriptions if (!_nodeSubscribers.ContainsKey(source)) { _nodeSubscribers.Add(source, 0); SubscribeAll(); done = true; } break; case NodeCommands.CMD_DELETE_NODE_LISTENER: if (_nodeSubscribers.ContainsKey(source)) { _nodeSubscribers.Remove(source); UnsubscribeAll(); done = true; } break; #endregion #region information commands case NodeCommands.CMD_READ_ALL: value = stack.PopByte(); //mask UpdateNodeStatus((byte)value); _bus.Payload = Status.ToArray(); done = true; break; case NodeCommands.CMD_GET_INFO: UpdateNodeInfo(); var array = NodeSerializer.Serialize(this); _bus.Payload = array; done = true; break; case NodeCommands.CMD_GET_NAME_INFO: //Subnode info name = stack.PopName(); var node = GetSubnode(name); if (node != null) { _bus.Payload = node.ToArray(); done = true; } break; #endregion #region General pin commands case NodeCommands.CMD_ACTIVATE: name = stack.PopName(); pin = GetPin(name); if (pin != null) { pin.Activate(); done = true; } break; case NodeCommands.CMD_DEACTIVATE: name = stack.PopName(); pin = GetPin(name); if (pin != null) { pin.Deactivate(); done = true; } break; case NodeCommands.CMD_SET_PIN: pin = new Pin(_hal, _scheduler); PinSerializer.DeSerialize(datain, ref pin); //pin = new Pin(datain, _hal, _scheduler); var oldPin = Pins.FirstOrDefault(p => p.Index == pin.Index); if (oldPin != null) Pins.Remove(oldPin); Pins.Add(pin); done = true; break; case NodeCommands.CMD_CONNECT: //var wire = new Wire(datain, this, _bus); var wire = new Wire(); WireSerializer.DeSerialize(datain, ref wire); wire.Input = Pins.FirstOrDefault(p => p.Name == wire.Input.Name); var oldWire = Wires.FirstOrDefault(w => w.Index == wire.Index); if (oldWire != null) Wires.Remove(oldWire); Wires.Add(wire); done = true; break; case NodeCommands.CMD_ADD_PIN_LISTENER: //Device name name = stack.PopName(); pin = GetPin(name); if (pin != null) { //Add pin to subscriptions if (!_pinSubscribers.ContainsKey(source + "." + name)) _pinSubscribers.Add(source + "." + name, pin); done = true; } break; case NodeCommands.CMD_DELETE_PIN_LISTENER: //Device name name = stack.PopName(); pin = GetPin(name); if (pin != null) { //Add pin to subscriptions if (_pinSubscribers.ContainsKey(source + "." + name)) _pinSubscribers.Remove(source + "." + name); done = true; } break; case NodeCommands.CMD_PUSH_PIN_EVENT: if (OnPinEvent != null) { OnPinEvent(source, new PinEvent(datain)); } done = true; break; #endregion #region Pins digital write commands case NodeCommands.CMD_CHANGE_ALL_DIGITAL: value = stack.PopByte(); foreach (var p in Pins) { p.Change(value); } done = true; break; case NodeCommands.CMD_CHANGE_DIGITAL: index = stack.PopByte(); value = stack.PopByte(); pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.Change(value); done = true; } break; case NodeCommands.CMD_TOGGLE_DIGITAL: index = stack.PopByte(); pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.Toggle(); done = true; } break; case NodeCommands.CMD_TIMED_DIGITAL: index = stack.PopByte(); width = stack.PopByte(); value = stack.PopByte(); pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.TimedOutput(width, value); done = true; } break; case NodeCommands.CMD_DELAY_DIGITAL: index = stack.PopByte(); delay = stack.PopByte(); value = stack.PopByte(); pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.DelayOutput(delay, value); done = true; } break; case NodeCommands.CMD_DELAY_TOGGLE_DIGITAL: index = stack.PopByte(); delay = stack.PopByte(); pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.DelayToggle(delay); done = true; } break; case NodeCommands.CMD_PULSE_DIGITAL: index = stack.PopByte(); delay = stack.PopByte(); width = stack.PopByte(); value = stack.PopByte(); pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.PulsedOutput(delay, width, value); done = true; } break; case NodeCommands.CMD_CYCLE_DIGITAL: index = stack.PopByte(); delay = stack.PopByte(); width = stack.PopByte(); value = stack.PopByte(); //cycles pin = GetPin(index, PinTypes.Output); if (pin != null) { pin.CycledOutput(delay, width, value); done = true; } break; #endregion #region Pins analog/pwm write commands case NodeCommands.CMD_CHANGE_PWM: index = stack.PopByte(); delay = stack.PopByte(); //high pulse width = stack.PopByte(); //total pulse pin = GetPin(index, PinTypes.Pwm); if (pin != null) { pin.ChangePwm(delay, width); done = true; } break; case NodeCommands.CMD_DELTA_PWM: index = stack.PopByte(); value = stack.PopInt16(); pin = GetPin(index, PinTypes.Pwm); if (pin != null) { pin.ChangeDelta(value); done = true; } break; case NodeCommands.CMD_FADE_PWM: index = stack.PopByte(); //type = (PinTypes)stack.PopByte(); var startValue = stack.PopUInt16(); var endValue = stack.PopUInt16(); value = stack.PopByte(); //steps delay = stack.PopByte(); pin = GetPin(index, PinTypes.Pwm); if (pin != null) { pin.Fade(startValue, endValue, (byte)value, delay); done = true; } break; case NodeCommands.CMD_CHANGE_PIN: name = stack.PopName(); value = stack.PopInt32(); pin = GetPin(name); if (pin != null) { pin.Change(value); done = true; } break; #endregion #region Pins read commands case NodeCommands.CMD_GET_PIN_INFO: index = stack.PopByte(); value = stack.PopByte(); pin = GetPin(index, (PinTypes)value); if (pin != null) { _bus.Payload = PinSerializer.Serialize(pin); done = true; } break; case NodeCommands.CMD_GET_CONNECT_INFO: index = stack.PopByte(); wire = Wires.FirstOrDefault(w => w.Index == index); if (wire != null) { array = WireSerializer.Serialize(wire); _bus.Payload = array; done = true; } break; case NodeCommands.CMD_READ_PIN: name = stack.PopName(); pin = GetPin(name); if (pin != null) { //Get pin value var evt = new PinEvent(name, pin.Read(), pin.IsActive()); _bus.Payload = evt.ToArray(); done = true; } break; case NodeCommands.CMD_READ_LAST_INPUT: dataOut.AddRange(FixedString.ToPaddedArray(Status.LastActivatedInput, HBusSettings.NameLength, ' ')); _bus.Payload = dataOut.ToArray(); done = true; break; case NodeCommands.CMD_READ_LAST_ACTIVE: dataOut.AddRange(FixedString.ToPaddedArray(Status.LastActivatedOutput, HBusSettings.NameLength, ' ')); _bus.Payload = dataOut.ToArray(); done = true; break; #endregion #region Device commands case NodeCommands.CMD_GET_DEVICE_INFO: index = stack.PopByte(); device = GetDevice(index); if (device != null) { array = DeviceSerializer.Serialize(device); _bus.Payload = array; done = true; } break; case NodeCommands.CMD_GET_DEVICE_STATUS: name = stack.PopName(); device = GetDevice(name); if (device != null) { var status = new DeviceStatus(device.Index, device.Name, device.Status); _bus.Payload = status.ToArray(); done = true; } break; case NodeCommands.CMD_EXECUTE_DEVICE_ACTION: //Device name var action = new DeviceAction(datain); device = GetDevice(action.Device); //Execute action if (device != null) { device.ExecuteAction(action); done = true; } break; case NodeCommands.CMD_ADD_DEVICE_LISTENER: //Device name name = stack.PopName(); device = GetDevice(name); //Execute action if (device != null) { if (!_deviceSubscribers.ContainsKey(source + "." + name)) _deviceSubscribers.Add(source + "." + name, device); done = true; } break; case NodeCommands.CMD_DELETE_DEVICE_LISTENER: //Device name name = stack.PopName(); device = GetDevice(name); //Execute action if (device != null) { if (_deviceSubscribers.ContainsKey(source + "." + name)) _deviceSubscribers.Remove(source + "." + name); done = true; } break; case NodeCommands.CMD_PUSH_DEVICE_EVENT: if (OnDeviceEvent != null) { var evt = new DeviceEvent(datain); OnDeviceEvent(source, evt); done = true; } break; #endregion #region Sensor commands case NodeCommands.CMD_GET_SENSOR_INFO: index = stack.PopByte(); sensor = GetSensor(index); if (sensor != null) { array = SensorSerializer.Serialize(sensor); _bus.Payload = array; done = true; } break; case NodeCommands.CMD_READ_SENSOR: //Sensor name name = stack.PopName(); sensor = GetSensor(name); if (sensor != null) { _bus.Payload = sensor.Read().ToArray(); done = true; } break; case NodeCommands.CMD_RESET_SENSOR: //Sensor name name = stack.PopName(); sensor = GetSensor(name); if (sensor != null) { sensor.Reset(); done = true; } break; case NodeCommands.CMD_ADD_SENSOR_LISTENER: //Sensor name name = stack.PopName(); var interval = stack.PopByte(); //interval var expire = stack.PopUInt16(); //Expires sensor = GetSensor(name); if (sensor != null) { if (_sensorSubscribers.All(s => s.Sensor != sensor)) _sensorSubscribers.Add(new SensorSubscriber(source, sensor, interval, expire)); done = true; } break; case NodeCommands.CMD_DELETE_SENSOR_LISTENER: //Sensor name name = stack.PopName(); sensor = GetSensor(name); if (sensor != null) { var sub = _sensorSubscribers.FirstOrDefault(s => s.Address == source); if (sub.Sensor != null) _sensorSubscribers.Remove(sub); done = true; } break; case NodeCommands.CMD_PUSH_SENSOR_READ: if (OnSensorRead != null) { OnSensorRead(source, new SensorRead(datain)); } done = true; break; #endregion #region Obolete / unsupported commands //case NodeCommands.CMD_MULTI_ACTIVATE: // //delay = stack.PopByte(); // //var names = stack.PopNames(); // //MultiActivateOutput(names, delay); // SetError(NodeErrorCodes.CommandNotSupported); // break; //case NodeCommands.CMD_READ_KEY: // //value = GetKeyPressed(); // //_bus.Payload = new[] { (byte)value }; // SetError(NodeErrorCodes.CommandNotSupported); // break; #endregion default: SetError(NodeErrorCodes.CommandNotSupported); break; } return done; } catch (Exception ex) { SetError(NodeErrorCodes.GenericError); Log.Error(string.Format("error occurred while processing command {0} for main node {1}", command, Name), ex); } return false; }