OnSwitchTrue Program .AddOption("DeviceType", "Serial", "Device Type (Serial, Ethernet)", "text") .AddOption("IPAddress", "127.0.0.1", "Ethernet IP address", "text") .AddOption("TCPPort", "5003", "Ethernet Port", "text") .AddOption("COMPort", "/dev/ttyUSB0", "Serial Port", "text") .AddOption("BaudRate", "115200", "Serial Baud rate", "text") .AddOption("InclusionMode", "True", "Inclusion Mode always on (True/False)", "text") .AddOption("GroupSubDevices", "True", "Group Subdevices with ID < 15 (True/False)", "text") .Run(); const string _HG_DOMAIN = "HomeAutomation.MySensors"; string DeviceType = Program.Option("DeviceType").Value.ToLower(); bool InclusionMode = Convert.ToBoolean(Program.Option("InclusionMode").Value.ToLower()); bool GroupSubDevices = Convert.ToBoolean(Program.Option("GroupSubDevices").Value.ToLower()); Func<int> GetNewNodeId = () => { int maxId = 0; Modules.InDomain(_HG_DOMAIN).Each( (module) => { string adr = module.Instance.Address; if (adr.Contains(".")) { adr = adr.Split('.')[0]; } if (Convert.ToInt32(adr) > maxId) { maxId = Convert.ToInt32(adr); } return false; }); return maxId + 1; }; Action<string> sendcommand = (string messages) => { // send command switch(DeviceType){ case "ethernet": TcpClient.SendMessage(messages); break; case "serial": SerialPort.SendMessage(messages); break; } }; Action<string> HandleStringReceived = (string incoming) => { // this will be called every time a message is received from serial port //Program.Notify("TCP String", incoming); Pause(5); string[] message = incoming.Split(';'); if (message.Length == 6) { //Program.Notify("SerialPort String", incoming); Pause(0.5); // node-id ; child-sensor-id ; message-type ; ack ; sub-type ; payload \n int nodeId = Convert.ToInt32(message[0]); int childSensorId = Convert.ToInt32(message[1]); int messageType = Convert.ToInt32(message[2]); string ack = message[3]; int subType = Convert.ToInt32(message[4]); string payload = message[5]; string parameterName = String.Format("ChildSensorId {0}", childSensorId); // HomeGenie Address is [NodeId].[ChildeSensorId], for example 6.1 string myNodeId = nodeId.ToString(); // If the deviceId is 15 or higher or GroupSubDevices is false, it has its own seperate widget if (childSensorId >= 15 || GroupSubDevices == false || subType == 4) { myNodeId = String.Format("{0}.{1}", nodeId, childSensorId); } // get the corresponding module var module = Modules.InDomain(_HG_DOMAIN).WithAddress(myNodeId).Get(); // PRESENTATION if (messageType == 0 && InclusionMode) // Presentation { // CREATE MODULE string hgType = string.Empty; string hgWidget = string.Empty; string parameterValue = string.Empty; switch(subType){ case 0: // S_DOOR hgType = "DoorWindow"; hgWidget = "homegenie/generic/doorwindow"; parameterValue = "S_DOOR"; break; case 1: // S_MOTION hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_MOTION"; break; case 3: // S_LIGHT / S_BINARY hgType = "Switch"; hgWidget = "homegenie/generic/switch"; parameterValue = "S_BINARY"; break; case 4: // ??? hgType = "Dimmer"; hgWidget = "homegenie/generic/dimmer"; parameterValue = "S_DIMMER"; break; case 6: // S_TEMP hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_TEMP"; break; case 7: // S_HUM hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_HUM"; break; case 11: // S_UV hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_UV"; break; case 13: // S_POWER hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_POWER"; break; case 15: // S_DISTANCE hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_DISTANCE"; break; case 16: // S_LIGHT_LEVEL hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_LIGHT_LEVEL"; break; case 19: // S_LOCK hgType = "DoorWindow"; hgWidget = "homegenie/generic/doorlock"; parameterValue = "S_LOCK"; break; case 20: // S_IR (Infrared device) hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_IR"; break; case 21: // S_WATER hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_WATER"; break; case 26: // S_RGB_LIGHT hgType = "Dimmer"; hgWidget = "homegenie/generic/colorlight"; parameterValue = "S_RGB_LIGHT"; break; case 37: // S_GAS hgType = "Sensor"; hgWidget = "homegenie/generic/sensor"; parameterValue = "S_GAS"; break; } // Create module // domain: Domain. // address: Address. // type: Generic, Program, Switch, Light, Dimmer, Sensor, Temperature, Siren, Fan, Thermostat, Shutter, DoorWindow, MediaTransmitter, MediaReceiver // widget: Empty string or the path of the widget to be associated to the virtual module. if (module.Instance == null) { // Module doesn't exist, create it. Program.AddVirtualModule(_HG_DOMAIN, myNodeId, hgType, hgWidget); //Alert the user Program.Notify(_HG_DOMAIN, String.Format("Node added: {0} with Id {1}", hgType, myNodeId)); // And get the newly created module module = Modules.InDomain(_HG_DOMAIN).WithAddress(myNodeId).Get(); } if (String.IsNullOrWhiteSpace(module.Instance.Name) && !String.IsNullOrWhiteSpace(payload)) { // Name given, add it to the widget module.Instance.Name = payload; } // Add META data if not found if (String.IsNullOrWhiteSpace(module.Parameter(parameterName).Value)) { module.Parameter(parameterName).Value = parameterValue; } } else if (messageType == 1) // Set { Program.Notify("My String", incoming);Pause(1); // Status.Level, Status.Battery, Sensor.Generic, Sensor.Temperature, Sensor.Luminance, Sensor.Humidity, // Sensor.DoorWindow, Sensor.MotionDetect, Sensor.Alarm, Sensor.CarbonMonoxide, Sensor.CarbonDioxide, // Sensor.Smoke, Sensor.Heat, Sensor.Flood, Sensor.Tamper, Meter.Watts string hgSubType = string.Empty; switch(subType){ case 0: // V_TEMP hgSubType = "Sensor.Temperature"; break; case 1: // V_HUM hgSubType = "Sensor.Humidity"; break; case 2: // V_STATUS, V_LIGHT // Binary level hgSubType = "Status.Level"; break; case 3: // V_DIMMER, V_PERCENTAGE hgSubType = "Status.Level"; // status.percentage? break; case 4: // V_DIMMER, V_PERCENTAGE hgSubType = "Status.Level"; // status.percentage? break; case 13: // V_DISTANCE hgSubType = "Sensor.Distance"; break; case 16: // V_TRIPPED // V_TRIPPED can relate to different Sensor types switch(module.Parameter(parameterName).Value){ case "S_DOOR": hgSubType = "Sensor.DoorWindow"; break; case "S_MOTION": hgSubType = "Sensor.MotionDetect"; break; case "S_SMOKE": hgSubType = "Sensor.Smoke"; break; case "S_MOISTURE": case "S_WATER_LEAK": hgSubType = "Sensor.Flood"; break; } break; case 17: // V_WATT hgSubType = "Meter.Watts"; break; case 18: // V_KWH hgSubType = "Meter.KilowattHour"; break; case 23: // V_LIGHT_LEVEL : Uncalibrated light level. 0-100%. Use V_LEVEL for light level in lux. hgSubType = "Sensor.Luminance"; break; case 32: // V_IR_SEND case 33: // V_IR_RECEIVE hgSubType = "Sensor.InfraRed"; break; case 34: // V_FLOW hgSubType = "Sensor.Flow"; break; case 35: // V_VOLUME hgSubType = "Sensor.Volume"; break; case 36: // V_LOCK_STATUS hgSubType = "Status.DoorLock"; if (payload == "0") {payload = "Unsecured";} else {payload = "Secured";} break; case 37: // V_LEVEL // V_LEVEL can relate to different Sensor types switch(module.Parameter(parameterName).Value){ case "S_DUST": case "S_AIR_QUALITY": case "S_SOUND": // (dB) case "S_VIBRATION": // (hz) case "S_LIGHT_LEVEL": // Calibrated Light Level (Lumens) hgSubType = "Sensor.Luminance"; break; } break; case 39: //V_CURRENT Current level S_MULTIMETER hgSubType = "Meter.Ampere"; break; case 40: // V_RGB hgSubType = "Status.ColorRgb"; break; /* case 54: // Reactive power: volt-ampere reactive (var) S_POWER hgSubType = "Meter.Amper"; break; case 55: // Apparent power: volt-ampere (VA) S_POWER hgSubType = "Meter.Amper";*/ break; } Program.RaiseEvent(module, hgSubType, payload, myNodeId + " - " + payload); } else if (messageType == 2) // Req { // TODO } else if (messageType == 3) // Internal { //Program.Notify("SerialPort Internal", incoming); Pause(0.5); string hgSubType = string.Empty; switch(subType){ case 0: // I_BATTERY_LEVEL hgSubType = "Status.Battery"; Program.RaiseEvent(module, hgSubType, payload, myNodeId + " - " + payload); break; case 3: // I_ID_REQUEST (eg. 255;255;3;0;3;) // Get a new Id and send //TcpClient.SendMessage(String.Format("255;255;3;0;4;{0}\n", GetNewNodeId())); sendcommand(String.Format("255;255;3;0;4;{0}\n", GetNewNodeId())); break; case 5: // I_INCLUSION_MODE InclusionMode = (payload == "1"); // 1: On, 2: Off break; } } } }; Action<bool> HandleStatusChanged = (bool connected) => { // this will be called every time the connection status changes Program.Notify(String.Format("MySensors {0} Gateway", Program.Option("DeviceType").Value), connected ? "CONNECTED!" : "DISCONNECTED!"); }; // CONNECTION switch(DeviceType){ case "ethernet": string IPAddress = Program.Option("IPAddress").Value; int TCPPort = Convert.ToInt32(Program.Option("TCPPort").Value); TcpClient .Service(IPAddress) .OnStatusChanged( HandleStatusChanged ) .OnStringReceived( HandleStringReceived ) .Connect( TCPPort ); break; case "serial": string comPort = Program.Option("COMPort").Value; int baudRate = Convert.ToInt32(Program.Option("BaudRate").Value); SerialPort .WithName( comPort ) .OnStatusChanged( HandleStatusChanged ) .OnStringReceived( HandleStringReceived ) .Connect( baudRate ); break; default: Program.Notify("ERROR:", String.Format("Unknown device type: {0}", Program.Option("DeviceType").Value)); break; } // open the serial port channel and register handlers When.WebServiceCallReceived(_HG_DOMAIN, ( args ) => { try { //Program.Notify("HomeAutomation.MySensors incoming", args.ToString()); Pause(1); // EXAMPLE for Switch: HomeAutomation.MySensors/27.14/Control.On/undefined string[] reqs = ((string)args).Split('/'); //Program.Notify("0", reqs[0]); Pause(1); //Program.Notify("1", reqs[1]); Pause(1); //Program.Notify("2", reqs[2]); Pause(1); //Program.Notify("3", reqs[3]); Pause(1); // reqs[1] = ID (21 or 21.11) // reqs[2] = Command (Control.On) // reqs[3] = Value (can be null) // reqs[4] = TIMESTAMP //Needs to be converted to something like this "27;14;1;0;2;1\n"; nodeID, childSensorId, messageType, ack, subType, Payload var nodeId = reqs[1].Split('.')[0]; var childSensorId = reqs[1].Split('.')[1]; int subType = 0; string setValue = ""; var module = Modules.InDomain(_HG_DOMAIN).WithAddress(reqs[1]).Get(); if (module.IsOfDeviceType("Switch") || module.IsOfDeviceType("Dimmer")) { if (module.IsOfDeviceType("Switch")) {subType = 2;} //V_STATUS, V_LIGHT if (module.IsOfDeviceType("Dimmer")) {subType = 3;} //V_DIMMER if (reqs[2] == "Control.Off") { setValue = "0"; } else if (reqs[2] == "Control.On") { if (module.IsOfDeviceType("Switch")) {setValue = "1";} //V_STATUS, V_LIGHT if (module.IsOfDeviceType("Dimmer")) {setValue = "100";} //V_DIMMER } else if (reqs[2] == "Control.Toggle") { double level = module.Parameter("Status.Level").DecimalValue; if (level > 0) {setValue = "0";} else { if (module.IsOfDeviceType("Switch")) {setValue = "1";} //V_STATUS, V_LIGHT if (module.IsOfDeviceType("Dimmer")) {setValue = "100";} //V_DIMMER } } else if (reqs[2] == "Control.Level") { //Program.Notify("Control.Level from HG", reqs[3].ToString()); Pause(1); ///// setValue = reqs[3].ToString(); ///// //setValue = (100 * Convert.ToInt32(reqs[3])).ToString(); } else if (reqs[2] == "Control.ColorRgb") { subType = 40; // V_RGB setValue = reqs[3].ToString(); } } //string testCommand = "27;14;1;0;2;1\n"; string theCommand = String.Format("{0};{1};{2};{3};{4};{5}\n", nodeId, childSensorId, "1", "0", subType, setValue); // send the message //Program.Notify("MySensors Info", theCommand);Pause(1); sendcommand(theCommand); // update if (reqs[2] == "Control.Level") { //theCommand = (double.Parse(theCommand)/100).ToString(); setValue = (double.Parse(setValue)/100).ToString(); } Program.RaiseEvent(module, "Status.Level", setValue, setValue); //Program.RaiseEvent(module, "Status.Level", (double.Parse(setValue)/100).ToString(), (double.Parse(setValue)/100).ToString()); return "{ 'ResponseValue' : 'OK' }"; } catch (Exception e) { Program.Notify("HomeAutomation.MySensors ERROR!", e.Message); Pause(2); Program.Notify("HomeAutomation.MySensors ERROR!", args.ToString()); return "{ 'ResponseValue' : 'OK' }"; } }); Program.GoBackground(); [] HomeAutomation.HomeGenie.Automation
1000
MySensors Gateway MySensors Gateway. (Supports both Serial and Ethernet Gateways) See https://www.mysensors.org/ for more information. test 2016-11-10T20:01:57.700155Z 2016-11-10T20:01:57.961425Z CSharp true