PHP-Code:
<?
print ( $_IPS['VALUE']);
$mysensors_base_category = IPS_GetParent($_IPS['SELF']);
$mysensors_client_socket = 19416 /*[Client Socket MySensors]*/;
$topic_level = explode(";", $_IPS['VALUE']);
$node_id = $topic_level[0];
$child_id = $topic_level[1];
$message_type = $topic_level[2];
$ack = $topic_level[3];
$sub_type = $topic_level[4];
$payload = trim(@$topic_level[5], "\n");; //sometimes no payload, ignore.
$ms_msg_type = array(
0 => 'presentation',
1 => 'set',
2 => 'req',
3 => 'internal',
4 => 'stream',
);
$ms_s_type = array(
0 => 'S_DOOR',
1 => 'S_MOTION',
2 => 'S_SMOKE',
//3 => 'S_LIGHT',
3 => 'S_BINARY',
4 => 'S_DIMMER',
5 => 'S_COVER',
6 => 'S_TEMP',
7 => 'S_HUM',
8 => 'S_BARO',
9 => 'S_WIND',
10 => 'S_RAIN',
11 => 'S_UV',
12 => 'S_WEIGHT',
13 => 'S_POWER',
14 => 'S_HEATER',
15 => 'S_DISTANCE',
16 => 'S_LIGHT_LEVEL',
17 => 'S_ARDUINO_NODE',
18 => 'S_ARDUINO_REPEATER_NODE',
19 => 'S_LOCK',
20 => 'S_IR',
21 => 'S_WATER',
22 => 'S_AIR_QUALITY',
23 => 'S_CUSTOM',
24 => 'S_DUST',
25 => 'S_SCENE_CONTROLLER',
26 => 'S_RGB_LIGHT',
27 => 'S_RGBW_LIGHT',
28 => 'S_COLOR_SENSOR',
29 => 'S_HVAC',
30 => 'S_MULTIMETER',
31 => 'S_SPRINKLER',
32 => 'S_WATER_LEAK',
33 => 'S_SOUND',
34 => 'S_VIBRATION',
35 => 'S_MOISTURE',
255 => 'S_PRESENTATION',
);
/*
0 Legt eine Variable vom Typ Boolean an
1 Legt eine Variable vom Typ Integer an
2 Legt eine Variable vom Typ Float an
3 Legt eine Variable vom Typ String an
*/
/*
~Mode.HM
~Milliampere.HM
~Temperature.HM
~Window.HM
~Electricity.HM
~Motion.HM
~Volt.230
~Raining
~ShutterPosition.255
~ShutterAssociation
~Battery.Reversed
~WindDirection.Text
~WindDirection
~WindSpeed.ms
~WindSpeed.kmh
~Motion
~Valve.F
~Battery.100
~ShutterPosition.100
~Intensity.100
~Temperature.Difference
~Motion.Reversed
~Humidity.F
~Presence.Reversed
~Valve
~Temperature
~Illumination.F
~Temperature.Room
~Temperature.Fahrenheit
~Intensity.32767
~MailMessages
~Occurrence.CO2
~AirPressure.F
~Alert
~WindDirection.F
~UVIndex
~Switch
~Intensity.1
~Battery
~Illumination
~Presence
~Lock.Reversed
~HTMLBox
~Alert.Reversed
~Brightness.HM
~ShutterMove
~Window.Reversed
~Volt
~Shutter
~Lock
~Ampere
~Ampere.16
~Watt.3680
~Humidity
~Watt.14490
~Hertz
~Hertz.50
~Intensity.255
~Electricity
~Water
~Gas
~Power
~Window
~Flow
~String
~UnixTimestamp
~TextBox
~Rainfall
~HexColor
~AirPressure
*/
//arrays to be finished...
$ms_v_type = array(
0 => array('v_type_name' => 'V_TEMP', 'ips_v_type' => 2, 'ips_v_profile' => '~Temperature'),
1 => array('v_type_name' => 'V_HUM', 'ips_v_type' => 2, 'ips_v_profile' => '~Humidity.F'),
2 => array('v_type_name' => 'V_STATUS', 'ips_v_type' => 0, 'ips_v_profile' => '~Switch'),
//2 => 'V_LIGHT',
3 => array('v_type_name' => 'V_PERCENTAGE','ips_v_type' => 2, 'ips_v_profile' => '~Intensity.100'),
//3 => 'V_DIMMER',
4 => array('v_type_name' => 'V_PRESSURE', 'ips_v_type' => 2, 'ips_v_profile' => '~AirPressure'),
5 => 'V_FORECAST',
6 => 'V_RAIN',
7 => 'V_RAINRATE',
8 => 'V_WIND',
9 => 'V_GUST',
10 => 'V_DIRECTION',
11 => 'V_UV',
12 => 'V_WEIGHT',
13 => 'V_DISTANCE',
14 => 'V_IMPEDANCE',
15 => 'V_ARMED',
16 => 'V_TRIPPED',
17 => 'V_WATT',
18 => 'V_KWH',
19 => 'V_SCENE_ON',
20 => 'V_SCENE_OFF',
21 => 'V_HVAC_FLOW_STATE',
22 => 'V_HVAC_SPEED',
23 => 'V_LIGHT_LEVEL',
24 => 'V_VAR1',
25 => 'V_VAR2',
26 => 'V_VAR3',
27 => 'V_VAR4',
28 => 'V_VAR5',
29 => 'V_UP',
30 => 'V_DOWN',
31 => 'V_STOP',
32 => 'V_IR_SEND',
33 => 'V_IR_RECEIVE',
34 => 'V_FLOW',
35 => 'V_VOLUME',
36 => 'V_LOCK_STATUS',
37 => 'V_LEVEL',
38 => array('v_type_name' => 'V_VOLTAGE', 'ips_v_type' => 1, 'ips_v_profile' => '~Volt'), //well, actually mV...
39 => 'V_CURRENT',
40 => 'V_RGB',
41 => 'V_RGBW',
42 => 'V_ID',
43 => 'V_UNIT_PREFIX',
44 => 'V_HVAC_SETPOINT_COOL',
45 => 'V_HVAC_SETPOINT_HEAT',
46 => 'V_HVAC_FLOW_MODE',
);
$ms_i_type = array(
0 => 'I_BATTERY_LEVEL',
1 => 'I_TIME',
2 => 'I_VERSION',
3 => 'I_ID_REQUEST',
4 => 'I_ID_RESPONSE',
5 => 'I_INCLUSION_MODE',
6 => 'I_CONFIG',
7 => 'I_FIND_PARENT',
8 => 'I_FIND_PARENT_RESPONSE',
9 => 'I_LOG_MESSAGE',
10 => 'I_CHILDREN',
11 => 'I_SKETCH_NAME',
12 => 'I_SKETCH_VERSION',
13 => 'I_REBOOT',
14 => 'I_GATEWAY_READY',
15 => 'I_REQUEST_SIGNING',
16 => 'I_GET_NONCE',
17 => 'I_GET_NONCE_RESPONSE',
);
//parse different message types
switch ($ms_msg_type[$message_type])
{
//($node_id, $child_sensor_id, $message_type, $ack, $sub_type, $payload)
case 'presentation':
print "Node:" .$node_id
." - Child:" .$child_id
." - Func:" .$ms_msg_type[$message_type]
." - ACK:" .$ack
." - Sub-Type:" .$ms_s_type[$sub_type]//['v_type_name']
." - Payload:" .$payload
."\n";
$node_conf_var = create_node_conf($node_id);
$node_conf = unserialize(GetValueString($node_conf_var));
//a new node?
if (!@array_key_exists ('node_id_' .$node_id, $node_conf)) //ignore empty conf warning
{
echo "creating node instance\n";
$instance_id = IPS_CreateInstance("{485D0419-BE97-4548-AA9C-C083EB82E61E}"); //dummy
IPS_SetParent($instance_id, $mysensors_base_category);
IPS_SetName($instance_id, "node ID" .$node_id);
$node_conf['node_id_' .$node_id] = $instance_id;
}
//a new child?
if (!@array_key_exists ('child_id_' .$child_id, $node_conf)) //ignore empty conf warning
{
echo "creating child variable\n";
$child_var_id = IPS_CreateVariable(3); //since we don't know the var type yet, set it to string for the moment
IPS_SetParent($child_var_id, $node_conf['node_id_' .$node_id]);
IPS_SetName($child_var_id, "child ID" .$child_id .':' .$payload);
$node_conf['child_id_' .$child_id] = $child_var_id;
}
//should we acknolege? correct way to be checked..
if($ack === '1')
{
echo "send ack";
CSCK_SendText($mysensors_client_socket, $node_id .';' .$child_id .';' .$message_type .';1;' .$sub_type .';' .$payload .';' .chr(0x0a));
}
break;
case 'set':
print "Node:" .$node_id
." - Child:" .$child_id
." - Func:" .$ms_msg_type[$message_type]
." - ACK:" .$ack
." - Sub-Type:" .$ms_v_type[$sub_type]['v_type_name']
." - Payload:" .$payload
."\n";
$node_conf_var = get_node_conf($node_id);
//skip unknown nodes.
if(!$node_conf_var)
{
print "unknown node id" .$node_id ."- skipping";
exit;
}
$node_conf = unserialize(GetValueString($node_conf_var));
//var type is not 100% known during presentation. check if it was already updated.
if(IPS_GetVariable($node_conf['child_id_' .$child_id])['VariableType'] != $ms_v_type[$sub_type]['ips_v_type'])
{
Print "updating var type\n";
$old_var_name = IPS_GetName($node_conf['child_id_' .$child_id]);
IPS_DeleteVariable($node_conf['child_id_' .$child_id]);
$child_var_id = IPS_CreateVariable($ms_v_type[$sub_type]['ips_v_type']);
$node_conf['child_id_' .$child_id] = $child_var_id;
IPS_SetParent($child_var_id, $node_conf['node_id_' .$node_id]);
IPS_SetName($child_var_id, $old_var_name);
IPS_SetVariableCustomProfile($child_var_id, $ms_v_type[$sub_type]['ips_v_profile']);
}
//cast the payload into the right type and write it to ips variable
switch ($ms_v_type[$sub_type]['ips_v_type'])
{
case 0: SetValue($node_conf['child_id_' .$child_id], (bool)$payload); break; //it's bool
case 1: SetValue($node_conf['child_id_' .$child_id], (integer)$payload); break; //it's int
case 2: SetValue($node_conf['child_id_' .$child_id], (float)$payload); break; //it's float
case 3: SetValue($node_conf['child_id_' .$child_id], (string)$payload); break; //it's string
}
break;
case 'req':
print "Node:" .$node_id
." - Child:" .$child_id
." - Func:" .$ms_msg_type[$message_type]
." - ACK:" .$ack
." - Sub-Type:" .$ms_v_type[$sub_type]
." - Payload:" .$payload;
break;
case 'internal':
print "Node:" .$node_id
." - Child:" .$child_id
." - Func:" .$ms_msg_type[$message_type]
." - ACK:" .$ack
." - Sub-Type:" .$ms_i_type[$sub_type]
." - Payload:" .$payload;
switch ($ms_i_type[$sub_type])
{
case 'I_BATTERY_LEVEL':
//load conf and skip unknown nodes.
$node_conf_var = get_node_conf($node_id);
if(!$node_conf_var){print "unknown node id" .$node_id ."- skipping"; exit;}
$node_conf = unserialize(GetValueString($node_conf_var));
if(!array_key_exists('battery_level', $node_conf))
{
$var_id = IPS_CreateVariable(1);
$node_conf['battery_level'] = $var_id;
IPS_SetParent($var_id, $node_conf['node_id_' .$node_id]);
IPS_SetName($var_id, "Battery Level");
IPS_SetVariableCustomProfile($var_id, '~Battery.100');
}
SetValue($node_conf['battery_level'], (int)$payload);
break;
case 'I_SKETCH_NAME':
//load conf and skip unknown nodes.
$node_conf_var = get_node_conf($node_id);
if(!$node_conf_var){print "unknown node id" .$node_id ."- skipping"; exit;}
$node_conf = unserialize(GetValueString($node_conf_var));
if(!array_key_exists('I_SKETCH_NAME', $node_conf))
{
$var_id = IPS_CreateVariable(3);
$node_conf['I_SKETCH_NAME'] = $var_id;
IPS_SetParent($var_id, $node_conf['node_id_' .$node_id]);
IPS_SetName($var_id, "Sketch Name");
}
SetValue($node_conf['I_SKETCH_NAME'], $payload);
break;
case 'I_SKETCH_VERSION':
//load conf and skip unknown nodes.
$node_conf_var = get_node_conf($node_id);
if(!$node_conf_var){print "unknown node id" .$node_id ."- skipping"; exit;}
$node_conf = unserialize(GetValueString($node_conf_var));
if(!array_key_exists('I_SKETCH_VERSION', $node_conf))
{
$var_id = IPS_CreateVariable(3);
$node_conf['I_SKETCH_VERSION'] = $var_id;
IPS_SetParent($var_id, $node_conf['node_id_' .$node_id]);
IPS_SetName($var_id, "Sketch Version");
}
SetValue($node_conf['I_SKETCH_VERSION'], $payload);
break;
case 'I_ID_REQUEST':
//find a node addess free to assign
$id=1;
while ($id <= 254)
{
$free_node_id = @IPS_GetVariableIDByName('node_id_' .$id, $mysensors_base_category);
if(!$free_node_id) break;
$id++;
}
if ($id > 254)
{
print "no more free node IDs - skipping. \n";
exit;
}
echo 'sending new ID ' .$id ."\n";
CSCK_SendText($mysensors_client_socket, '255;255;3;0;4;' .$id .';' .chr(0x0a));
break;
case 'I_CONFIG':
echo 'send I_CONFIG';
//correct way? to be checked...
CSCK_SendText($mysensors_client_socket, $node_id .';' .$child_id .';3;0;6;M;' .chr(0x0a));
break;
}
break;
case 'stream':
echo 'stream is not supported, yet';
break;
}
if (isset($node_conf_var))
{
SetValueString($node_conf_var , serialize($node_conf));
print_r ($node_conf);
}
/*----------------------------------------------------------------------------*/
function create_node_conf($node_id)
{
$parent_category = IPS_GetParent($_IPS['SELF']);
$var_node_id = @IPS_GetVariableIDByName("node_id_" .$node_id, $parent_category);
if($var_node_id === false)
{
echo "creating missing node conf variable for ID:" .$node_id ."\n";
$var_node_id = IPS_CreateVariable(3);
IPS_SetName($var_node_id , "node_id_" .$node_id);
IPS_SetParent($var_node_id, $parent_category);
}
return $var_node_id;
}
function get_node_conf($node_id)
{
$parent_category = IPS_GetParent($_IPS['SELF']);
$var_node_id = @IPS_GetVariableIDByName("node_id_" .$node_id, $parent_category);
return $var_node_id;
}
?>