OnSwitchTrue
Program
.AddOption("IPAddress", "127.0.0.1", "IP address", "text")
.AddOption("TCPPort", "5003", "Port", "text")
.AddOption("InclusionMode", "True", "Inclusion Mode always on (True/False)", "text")
.AddOption("GroupSubDevices", "True", "Group Subdevices with ID > 10 (True/False)", "text")
.Run();
Func<int> GetNewNodeId = () =>
{
int maxId = 0;
Modules.InDomain("HomeAutomation.MySensors").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;
};
TcpClientHelper tcpConnection = new TcpClientHelper();
string IPAddress = Program.Option("IPAddress").Value;
int TCPPort = Convert.ToInt32(Program.Option("TCPPort").Value);
bool InclusionMode = Convert.ToBoolean(Program.Option("InclusionMode").Value.ToLower());
bool GroupSubDevices = Convert.ToBoolean(Program.Option("GroupSubDevices").Value.ToLower());
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 10 or higher or GroupSubDevices is false, it has its own seperate widget
if (childSensorId >= 10 || GroupSubDevices == false )
{
myNodeId = String.Format("{0}.{1}", nodeId, childSensorId);
}
// get the corresponding module
var module = Modules.InDomain("HomeAutomation.MySensors").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 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 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 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("HomeAutomation.MySensors", myNodeId, hgType, hgWidget);
//Alert the user
Program.Notify("HomeAutomation.MySensors", String.Format("Node added: {0} with Id {1}", hgType, myNodeId));
// And get the newly created module
module = Modules.InDomain("HomeAutomation.MySensors").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("SerialPort 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
hgSubType = "Status.Level";
break;
case 3: // V_DIMMER, V_PERCENTAGE
hgSubType = "Status.Level";
payload = (double.Parse(payload)/100).ToString();
break;
case 13: // V_DISTANCE
hgSubType = "Status.Level";
break;
case 16: // V_TRIPPED
// V_TRIPPED can relate to many different values
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;
default:
hgSubType = "Sensor.Generic";
break;
}
break;
case 17: // V_WATT
hgSubType = "Meter.Watts";
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.Generic";
break;
case 34: // V_FLOW
switch(module.Parameter(parameterName).Value){
case "S_WATER":
hgSubType = "Sensor.Generic";
break;
case "S_GAS":
hgSubType = "Sensor.Generic";
break;
default:
hgSubType = "Status.Generic";
break;
}
break;
case 35: // V_VOLUME
switch(module.Parameter(parameterName).Value){
case "S_WATER":
hgSubType = "Sensor.Generic";
break;
case "S_GAS":
hgSubType = "Sensor.Generic";
break;
default:
hgSubType = "Status.Generic";
break;
}
break;
case 37: // V_LEVEL
// V_LEVEL can relate to many different values
switch(module.Parameter(parameterName).Value){
case "S_LIGHT_LEVEL": // Calibrated Light Level (Lumens)
hgSubType = "Sensor.Luminance";
break;
default:
hgSubType = "Status.Level";
break;
}
break;
case 40: // V_RGB
hgSubType = "Status.ColorRgb";
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
tcpConnection.SendMessage(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("MySensors Ethernet Gateway", connected ? "CONNECTED!" : "DISCONNECTED!");
};
tcpConnection
.Service(IPAddress)
.OnStatusChanged( HandleStatusChanged )
.OnStringReceived( HandleStringReceived )
.Connect( TCPPort );
When.WebServiceCallReceived("HomeAutomation.MySensors", ( 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("HomeAutomation.MySensors").WithAddress(reqs[1]).Get();
if (module.IsOfDeviceType("Switch") || module.IsOfDeviceType("Dimmer"))
{
subType = 2; //V_STATUS, V_LIGHT
if (reqs[2] == "Control.Off")
{
setValue = "0";
}
else if (reqs[2] == "Control.On")
{
setValue = "1";
}
else if (reqs[2] == "Control.Toggle")
{
double level = module.Parameter("Status.Level").DecimalValue;
if (level > 0)
{setValue = "0";}
else
{setValue = "1";}
}
else if (reqs[2] == "Control.Level")
{
subType = 3; // V_PERCENTAGE, V_DIMMER
setValue = 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
tcpConnection.SendMessage(theCommand);
// update
if (reqs[2] == "Control.Level")
{
theCommand = (double.Parse(theCommand)/100).ToString();
}
Program.RaiseEvent(module, "Status.Level", setValue, setValue);
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 Ethernet Gateway
MySensors Ethernet Gateway. See https://www.mysensors.org/ for more information.
Interconnections
2016-10-14T19:47:14.945657Z
2016-10-14T19:47:15.060368Z
CSharp
true