Skip to content

Instantly share code, notes, and snippets.

@y8s
Created April 9, 2019 14:55
Show Gist options
  • Save y8s/d54bc37ce60a37f53ca77771e14e34a9 to your computer and use it in GitHub Desktop.
Save y8s/d54bc37ce60a37f53ca77771e14e34a9 to your computer and use it in GitHub Desktop.
Node-RED MySensors Payload Decoder Function
/* MySensors v2.3 Message Decoder
* Payload : JSON object
* Original author: www.projetsdiy.fr - oct. 2016
* Updated April 2019 by y8s
* Changes: Includes support for MySensors 2.3 Serial Protocol
* Returns (roughly) appropriate data types for each Set value (Integer, Float, String)
*/
var mySensorsMessage = {};
var newPayload = {};
var message = msg.payload.toString();
message = message.replace(/(\r\n|\n|\r)/gm, "");
var tokens = message.split(";");
if(tokens.length == 6)
{
mySensorsMessage.nodeId = parseInt(tokens[0]);
mySensorsMessage.childSensorId= parseInt(tokens[1]);
mySensorsMessage.messageType = parseInt(tokens[2]);
mySensorsMessage.ack = parseInt(tokens[3]);
mySensorsMessage.subType = parseInt(tokens[4]);
mySensorsMessage.value = tokens[5];
var messageType = mySensorsMessage.messageType;
var subType = mySensorsMessage.subType;
var labelPresentation = ["S_DOOR","S_MOTION","S_SMOKE","S_BINARY","S_DIMMER","S_COVER","S_TEMP","S_HUM","S_BARO","S_WIND","S_RAIN","S_UV","S_WEIGHT","S_POWER","S_HEATER","S_DISTANCE","S_LIGHT_LEVEL","S_ARDUINO_NODE","S_ARDUINO_REPEATER_NODE","S_LOCK","S_IR","S_WATER","S_AIR_QUALITY","S_CUSTOM","S_DUST","S_SCENE_CONTROLLER","S_RGB_LIGHT","S_RGBW_LIGHT","S_COLOR_SENSOR","S_HVAC","S_MULTIMETER","S_SPRINKLER","S_WATER_LEAK","S_SOUND","S_VIBRATION","S_MOISTURE","S_INFO","S_GAS","S_GPS","S_WATER_QUALITY"];
var labelSet = ["V_TEMP","V_HUM","V_STATUS","V_PERCENTAGE","V_PRESSURE","V_FORECAST","V_RAIN","V_RAINRATE","V_WIND","V_GUST","V_DIRECTION","V_UV","V_WEIGHT","V_DISTANCE","V_IMPEDANCE","V_ARMED","V_TRIPPED","V_WATT","V_KWH","V_SCENE_ON","V_SCENE_OFF","V_HVAC_FLOW_STATE","V_HVAC_SPEED","V_LIGHT_LEVEL","V_VAR1","V_VAR2","V_VAR3","V_VAR4","V_VAR5","V_UP","V_DOWN","V_STOP","V_IR_SEND","V_IR_RECEIVE","V_FLOW","V_VOLUME","V_LOCK_STATUS","V_LEVEL","V_VOLTAGE","V_CURRENT","V_RGB","V_RGBW","V_ID","V_UNIT_PREFIX","V_HVAC_SETPOINT_COOL","V_HVAC_SETPOINT_HEAT","V_HVAC_FLOW_MODE","V_TEXT","V_CUSTOM","V_POSITION","V_IR_RECORD","V_PH","V_ORP","V_EC","V_VAR","V_VA","V_POWER_FACTOR"];
var labelInternal = ["I_BATTERY_LEVEL","I_TIME","I_VERSION","I_ID_REQUEST","I_ID_RESPONSE","I_INCLUSION_MODE","I_CONFIG","I_FIND_PARENT","I_FIND_PARENT_RESPONSE","I_LOG_MESSAGE","I_CHILDREN","I_SKETCH_NAME","I_SKETCH_VERSION","I_REBOOT","I_GATEWAY_READY","I_REQUEST_PRESENTATION","I_NONCE_REQUEST","I_NONCE_RESPONSE","I_HEARTBEAT_REQUEST","I_PRESENTATION","I_DISCOVER_REQUEST","I_DISCOVER_RESPONSE","I_HEARTBEAT_RESPONSE","I_LOCKED","I_PING","I_PONG","I_REGISTRATION_REQUEST","I_REGISTRATION_RESPONSE","I_DEBUG"];
switch (messageType) {
case 0: // Presentation
newPayload.mode = "Presentation";
newPayload.type = labelPresentation[subType];
break;
case 1: // Set
newPayload.nodeId= mySensorsMessage.nodeId;
newPayload.sensorId= mySensorsMessage.childSensorId;
newPayload.mode= "Set";
newPayload.type= subType;
newPayload.typeLabel= labelSet[subType];
// for these types, value is floating point:
if (subType == 0 || 1 || 3 || 4 || 6 || 7 || 8 || 9 || 10 || 11 || 12 || 13 || 14 || 17 || 18 || 23 || 34 || 37 || 38 || 39 || 44 || 45 || 46 || 51 || 52 || 53 || 54 || 55) {
newPayload.value= parseFloat(mySensorsMessage.value);
// for these types, value is integer (or boolean really)
} else if (subType == 2 || 15 || 16 || 36) {
newPayload.value= parseInt(mySensorsMessage.value);
} else {
newPayload.value= mySensorsMessage.value;
}
break;
case 2: // Req
newPayload.nodeId= mySensorsMessage.nodeId;
newPayload.sensorId= mySensorsMessage.childSensorId;
newPayload.mode= "Req";
newPayload.type= subType;
newPayload.typeLabel= labelSet[subType];
newPayload.value= parseInt(mySensorsMessage.value);
break;
case 3: // Internal
newPayload.nodeId= mySensorsMessage.nodeId;
newPayload.sensorId= mySensorsMessage.childSensorId;
newPayload.mode= "Internal";
newPayload.type= subType;
newPayload.typeLabel= labelInternal[subType];
newPayload.value= mySensorsMessage.value;
break;
case 4: // Stream - OTA firmware update
newPayload.nodeId= mySensorsMessage.nodeId;
newPayload.mode= "stream";
break;
default:
break;
}
msg.payload = newPayload;
} else {
msg.payload = "Error! Nothing to decode";
}
return msg;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment