Subversion Repositories HomeAutomation

Rev

Rev 2298 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1.  
  2. Sensor_ModuleNames    = [ "DS18x20", "FOST02", "BusVoltage", "SimpleDTMF", "DHT11", "VoltageCurrent", "ultrasonic", "flower", "NTC", "TC1047A", "LM335", "TCN75A"];
  3. SensorRf_ModuleNames    = [ "rfTransceive" ];
  4. Sensor_Intervals      = function() { return [ 1, 5, 10, 15, 20 ]; };
  5. Sensor_Aliases        = function() { return Module_GetAliasNames(Sensor_ModuleNames); };
  6. Sensor_AvailableIds   = function() { return Module_GetAvailableIds(Sensor_ModuleNames); };
  7.  
  8. function Sensor_SetReportInterval(alias_name, interval)
  9. {
  10.     if (arguments.length < 2)
  11.     {
  12.         Log("\033[31mNot enough parameters given.\033[0m\n");
  13.         return false;
  14.     }
  15.  
  16.     var aliases_data = Module_ResolveAlias(alias_name, Sensor_ModuleNames);
  17.     var found = false;
  18.  
  19.     for (var name in aliases_data)
  20.     {
  21.         var variables = {"Time"     : interval };
  22.         if (Module_SendMessage(aliases_data[name]["module_name"], aliases_data[name]["module_id"], "Report_Interval", variables))
  23.         {
  24.             Log("\033[32mCommand sent successfully to " + name + ".\033[0m\n");
  25.         }
  26.         else
  27.         {
  28.             Log("\033[31mFailed to send command to " + name + ".\033[0m\n");
  29.         }
  30.  
  31.         found = true;
  32.     }
  33.  
  34.     if (!found)
  35.     {
  36.         Log("\033[31mNo aliases by the name " + alias_name + " were applicable for this command.\033[0m\n");
  37.         return false;
  38.     }
  39.  
  40.     return true;
  41. }
  42. Console_RegisterCommand(Sensor_SetReportInterval, function(arg_index, args) { return Console_StandardAutocomplete(arg_index, args, Sensor_Aliases(), Sensor_Intervals()); });
  43.  
  44. Sensor_OnNewPhonenumberFunctions = [];
  45.  
  46. function Sensor_RegisterToNewPhonenumber(alias_name, callback)
  47. {
  48.   if (!Sensor_OnNewPhonenumberFunctions[alias_name])
  49.   {
  50.     Sensor_OnNewPhonenumberFunctions[alias_name] = [];
  51.   }
  52.  
  53.   Sensor_OnNewPhonenumberFunctions[alias_name].push(callback);
  54. }
  55.  
  56. Sensor_OnDeviceStateChangeFunctions = [];
  57.  
  58. function Sensor_RegisterToDeviceStateChange(alias_name, callback)
  59. {
  60.   if (!Sensor_OnDeviceStateChangeFunctions[alias_name])
  61.   {
  62.     Sensor_OnDeviceStateChangeFunctions[alias_name] = [];
  63.   }
  64.  
  65.   Sensor_OnDeviceStateChangeFunctions[alias_name].push(callback);
  66. }
  67.  
  68.  
  69. function Sensor_OnMessage(module_name, module_id, command, variables)
  70. {
  71.   if (in_array(Sensor_ModuleNames, module_name))
  72.   {
  73.     var aliases_data = Module_LookupAliases({
  74.       "module_name" : module_name,
  75.       "module_id"   : module_id,
  76.       "group"       : false
  77.     });
  78.  
  79.     switch (command)
  80.     {
  81.       case "Phonenumber":
  82.       {
  83.         for (var alias_name in aliases_data)
  84.         {
  85.           var number = variables["Number"];
  86.           var incommingCall = true;
  87.           var checkName = true;
  88.  
  89.           Log("received from DTMF:\"" + number + "\"");
  90.  
  91.           if (variables["Number"].length >= 6)
  92.           {
  93.             /* A seems to mean it is an incomming call! */
  94.             if (number.charAt(0) === 'A' || number.charAt(0) === 'D')
  95.             {
  96.               incommingCall = true;
  97.  
  98.               /* Remove leading A */
  99.               number = number.substring(1);
  100.             }
  101.             else /* Outgoing call */
  102.             {
  103.               incommingCall = false;
  104.             }
  105.  
  106.             /* A number can have a trailing C */
  107.             var endIndex = number.indexOf('C');
  108.  
  109.             if (endIndex !== -1)
  110.             {
  111.               /* Remove trailing C */
  112.               number = number.substring(0, endIndex);
  113.             }
  114.           }
  115.           else if (number == "B00C")
  116.           {
  117.             /* Unknown number */
  118.             number = "Unknown";
  119.             incommingCall = true;
  120.             checkName = false;
  121.           }
  122.           else if (number == "B10C")
  123.           {
  124.             /* Secret/protected number */
  125.             number = "Protected";
  126.             incommingCall = true;
  127.             checkName = false;
  128.           }
  129.           else
  130.           {
  131.             Log("DTMF decoded number is to short, number: \"" + number + "\", length: " + number.length);
  132.             return;
  133.           }
  134.          
  135.           /* Adding area code prefix if needed */
  136.           if (number.charAt(0) != '0' && checkName)
  137.           {
  138.             if (typeof sensorDefaultPhoneAreaCode === 'undefined')
  139.             {
  140.               Log("\033[31mOnlinePhonebook: please add sensorDefaultPhoneAreaCode = yourAreaCode to autostart.js, defaulting to 031\033[0m\n");
  141.               number = "031" + number;
  142.             }
  143.             else
  144.             {
  145.                 number = sensorDefaultPhoneAreaCode + number;
  146.             }
  147.           }
  148.  
  149.           /* Store number and direction in last values */
  150.           var lastValue = {};
  151.           var lastValueString = Storage_GetParameter("LastValues", alias_name);
  152.  
  153.           if (lastValueString)
  154.           {
  155.             lastValue = JSON.parse(lastValueString);
  156.           }
  157.  
  158.           var timestamp = get_time();
  159.  
  160.           lastValue["Phonenumber"] = { "value" : number, "timestamp" : timestamp };
  161.           lastValue["Direction"] = { "value" : incommingCall ? "in" : "out", "timestamp" : timestamp };
  162.  
  163.           Storage_SetParameter("LastValues", alias_name, JSON.stringify(lastValue));
  164.  
  165.  
  166.           /* Store number in phone call history */
  167.           var newValue = { "number" : number, "direction" : incommingCall ? "in" : "out", "module" : alias_name, "names" : [], "timestamp" : timestamp };
  168.  
  169.           Storage_SetParameter("PhoneCalls", timestamp, JSON.stringify(newValue));
  170.  
  171.  
  172.           /* Log the number */
  173.           Log("New number: " + number + ", direction: " + (incommingCall ? "in" : "out"));
  174.          
  175.           /* Lookup name */
  176.           if (checkName)
  177.           {
  178.             Sensor_StoreNumberInPhonebook(number, timestamp);
  179.           }
  180.  
  181.           var phonebookNumbers = Storage_GetJsonParamter("PhoneBook", number);
  182.           if (!phonebookNumbers)
  183.           {
  184.             phonebookNumbers = [];
  185.           }
  186.          
  187.           /* Call any potential subscribers */
  188.           if (Sensor_OnNewPhonenumberFunctions[alias_name])
  189.           {
  190.             for (var n in Sensor_OnNewPhonenumberFunctions[alias_name])
  191.             {
  192.               /* Call callback with arguments alias, number, direction */
  193.               Sensor_OnNewPhonenumberFunctions[alias_name][n](alias_name, number, incommingCall ? "in" : "out", phonebookNumbers);
  194.             }
  195.           }
  196.         }
  197.         break;
  198.       }
  199.       case "Voltage":
  200.       case "Temperature_Celsius":
  201.       {
  202.         if ((module_name == "DS18x20") && (variables["Value"] == 85))
  203.         {
  204.           Log("\033[31mDS18x20: Temperature conversion error: " + module_name + ":" + module_id + ", SensorId=" + variables["SensorId"] + "\033[0m");
  205.           break;
  206.         }
  207.       }
  208.       case "Humidity_Percent":
  209.       case "Percent":
  210.       case "Distance":
  211.       {
  212.         for (var alias_name in aliases_data)
  213.         {
  214.           if (aliases_data[alias_name]["specific"]["SensorId"] != variables["SensorId"])
  215.           {
  216.             continue;
  217.           }
  218.  
  219.           var last_value = {};
  220.           var last_value_string = Storage_GetParameter("LastValues", alias_name);
  221.  
  222.           if (last_value_string)
  223.           {
  224.             last_value = eval("(" + last_value_string + ")");
  225.           }
  226.       last_value[command] = { "value" : variables["Value"], "timestamp" : get_time() };
  227.           Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  228.         }
  229.  
  230.         break;
  231.       }
  232.     }
  233.   }
  234. }
  235. Module_RegisterToOnMessage("all", Sensor_OnMessage);
  236.  
  237. function SensorRf_OnMessage(module_name, module_id, command, variables)
  238. {
  239.  
  240.     if (in_array(SensorRf_ModuleNames, module_name))
  241.     {
  242.         var aliases_data = Module_LookupAliases({
  243.         "module_name" : module_name,
  244.         "module_id"   : module_id,
  245.         "group"       : false   });
  246.        
  247.         /* Must check sensor here in case no alias is stored the adress needs to be printed */
  248.         var RubicsonSuccess = "NoRubicsonSensor";
  249.         var OregonRainSuccess = "NoSensor";
  250.         var OregonTempHumSuccess = "NoSensor";
  251.         var OregonWindSuccess = "NoSensor";
  252.         var VikingSuccess = "NoVikingSensor";
  253.         var VikingSteakSuccess = "NoVikingSteakSensor";
  254.         var RubicsonStationSuccessPkt1 = "NoSensor";
  255.         var RubicsonStationSuccessPkt2 = "NoSensor";
  256.         if (variables["Protocol"] == "OregonRain")
  257.         {
  258.             /* ----------- Data order proto-data ------
  259.             * cc bb bb bb aa aa
  260.             * a   = Rain in 0.01 inches per hour
  261.             * b   = Total Rain in 0.001 inches
  262.             * cc   = 0xddefffff
  263.             *   dd = Channel
  264.             *   e  = Battery low flag
  265.             *   fffff = Lower part of rolling code
  266.             * -----------------------------*/
  267.             var data = variables["IRdata"];
  268.             var inchPerHour = (data)&0xFFFF;
  269.             inchPerHour = inchPerHour/100;
  270.             var totInch = (data>>>16)&0xFFFFFF;
  271.             totInch = totInch/1000;
  272.             var totMM = totInch * 25.4;
  273.             var mmPerHour = inchPerHour * 25.4;
  274.            
  275.             var addr = rshift(data,46)&0x3;
  276.             var bat = rshift(data,45)&0x1;
  277.             var unknown = rshift(data,40)&0x1F;
  278.  
  279.             OregonRainSuccess = "NotFound";
  280.            
  281.         } else if (variables["Protocol"] == "OregonTempHum")
  282.         {
  283.                /* ----------- Data order proto-data ------
  284.             * cc 00 00 bb bb aa
  285.             * aa   = Humidity in %
  286.             * bbbb = Temperature*10 in celcius
  287.             * cc   = 0xddefffff
  288.             *   dd = Channel
  289.             *   e  = Battery low flag
  290.             *   fffff = Lower part of rolling code
  291.             * -----------------------------*/  
  292.             var data = variables["IRdata"];
  293.             var humidity = (data)&0xFF;
  294.             var temp = (data>>>8)&0x7FFF;
  295.             var sign = (temp>>>23)&1;
  296.             if (sign > 0)
  297.             {
  298.                 temp = temp^0x7FFF;
  299.                 temp += 1;
  300.                 temp = -temp;
  301.             }
  302.             temp = temp/10;
  303.             var addr = rshift(data,46)&0x3;
  304.             var bat = rshift(data,45)&0x1;
  305.             var unknown = rshift(data,40)&0x1F;
  306.  
  307.             OregonTempHumSuccess = "NotFound";
  308.            
  309.         } else if (variables["Protocol"] == "OregonWind")
  310.         {
  311.             /* ----------- Data order proto-data ------
  312.             * cc 00 0d bb ba aa
  313.             * aaa  = wind speed average (in 0.1m/s)
  314.             * bbb  = wind speed current (in 0.1m/s)
  315.             * d    = Direction in 22.5 degrees
  316.             * cc   = 0xddefffff
  317.             *   dd = Channel
  318.             *   e  = Battery low flag
  319.             *   fffff = Lower part of rolling code
  320.             * -----------------------------*/
  321.             var data = variables["IRdata"];
  322.             var average = (data)&0xFFF;
  323.             average = average/10;
  324.            
  325.             var current = rshift(data,12)&0xFFF;
  326.             current = current/10;
  327.            
  328.             var direction = rshift(data,24)&0xF;
  329.             direction = direction*22.5;
  330.            
  331.             var addr = rshift(data,46)&0x3;
  332.             var bat = rshift(data,45)&0x1;
  333.             var unknown = rshift(data,40)&0x1F;
  334.  
  335.             OregonWindSuccess = "NotFound";
  336.            
  337.         } else if (variables["Protocol"] == "Rubicson")
  338.         {
  339.             /*
  340.                       ??? aaaaaaaa sttttttttttt hhhhhhhh cccccccc
  341.             341731651126    0b100 11111001 000011001011 00101110 00110110   20.3 46%
  342.             a = address, s = sign, t = temperature, h = humidity, c = crc
  343.             */
  344.             var data = variables["IRdata"];
  345.             var unknown = rshift(data,26)&0x3FF;
  346.             //var crc = data&0xFF;
  347.             //var humidity = (data>>>8)&0xFF;
  348.             var temp = (data>>>12)&0xFFF;
  349.             var addr = rshift(data,24)&0x3;
  350.             //var calccrc=crc8(rshift(data,8), 32);
  351.                    
  352.             var sign = (temp>>>11)&1;
  353.             if (sign > 0)
  354.             {
  355.                 temp = temp^0xFFF;
  356.                 temp += 1;
  357.                 temp = -temp;
  358.             }
  359.             temp = temp/10;
  360.  
  361.             RubicsonSuccess = "RubicsonNotFound";
  362.            
  363.         } else if (variables["Protocol"] == "Viking")
  364.         {
  365.             /*
  366.                               ppp aaaaaaaa sttttttttttt hhhhhhhh cccccccc
  367.             341731651126    0b100 11111001 000011001011 00101110 00110110   20.3 46%
  368.             p = protocol type, a = address, s = sign, t = temperature, h = humidity, c = crc
  369.             */
  370.             var data = variables["IRdata"];
  371.             var crc = data&0xFF;
  372.             var humidity = (data>>>8)&0xFF;
  373.             var temp = (data>>>16)&0xFFF;
  374.             var addr = rshift(data,28)&0xFF;
  375.             var type = rshift(data,36)&0xF;
  376.             var calccrc=crc8(rshift(data,8), 32);
  377.  
  378.             var sign = (temp>>>11)&1;
  379.             temp = temp&0x7FF;
  380.             if (sign > 0)
  381.             {
  382.                 temp = -temp;
  383.             }
  384.             temp = temp/10;
  385.  
  386.             VikingSuccess = "VikingNotFound";
  387.            
  388.             if (type != 4 && type != 3)
  389.             {
  390.                 Log("\033[33mWarning: VikingSensor, type="+type+", data="+data+"\033[0m");
  391.             }
  392.         } else if (variables["Protocol"] == "VikingSteak")
  393.         {
  394.             var data = variables["IRdata"];
  395.             var addr = (data>>>4)&0xFF;
  396.             var byte0 = rshift(data,32)&0xF;
  397.             var byte1 = rshift(data,28)&0xF;
  398.             var byte2 = rshift(data,24)&0xF;
  399.             var temp = Math.round((((((byte1^byte2)<<8)+((byte0^byte1)<<4)+byte0^10)-122)*5)/9);
  400.             VikingSteakSuccess = "VikingNotFound";
  401.         } else if (variables["Protocol"] == "RubicsonStn")
  402.         {
  403.             var data = variables["IRdata"];
  404.             var pkt = rshift(data,39)&0x1;
  405.             if (pkt == 0)  //This is the first part
  406.             {      
  407.                 /*
  408.                       aaaaaaaa 0dddsttt tttttttt hhhhhhhh wwwwwwww wwwwwwww
  409.                     0b11111001 11111001 00001100 10110010 11100011 01101111
  410.                 a = address = winddirection, s = sign, t = temperature, h = humidity, w = vindspeed
  411.                 */
  412.                 var windspeed_avg = (rshift(data,8) & 0xFF)*0.8;
  413.                 var windspeed_max = (data & 0xFF)*0.8;
  414.                 //var crc = data&0xFF;
  415.                 var humidity = rshift(data,16)&0xFF;
  416.                 var temp = rshift(data,24)&0xFFF;
  417.                 var winddirection = (rshift(data,36)&0x7)*360/8;
  418.                
  419.                 var addr = rshift(data,40)&0xFF;
  420.                 //var calccrc=crc8(rshift(data,8), 32);
  421.                        
  422.                 var sign = (temp>>>11)&1;
  423.                 if (sign > 0)
  424.                 {
  425.                     temp = temp^0xFFF;
  426.                     temp += 1;
  427.                     temp = -temp;
  428.                 }
  429.                 temp = temp/10;
  430.  
  431.                 RubicsonStationSuccessPkt1 = "NotFound";
  432.                
  433.                
  434.             } else //This is the second part
  435.             {
  436.                 /*
  437.                       aaaaaaaa 1------- -------b rrrrrrrr rrrrrrrr rrrrrrrr
  438.                     0b11111001 11111001 00001100 10110010 11100011 01101111
  439.                 a = address b = battery empty, r = rain
  440.                 */
  441.                 var battery = rshift(data,24) & 0x1;
  442.                 //var crc = data&0xFF;
  443.                 var rain = 0.4*(data&0xFFFFFF);
  444.                 var addr = rshift(data,40)&0xFF;
  445.  
  446.                 RubicsonStationSuccessPkt2 = "NotFound";
  447.             }
  448.            
  449.         }
  450.                
  451.         loopAliases:    /* Label to break nested */
  452.         for (var alias_name in aliases_data)
  453.         {
  454.             if (aliases_data[alias_name]["specific"]["Channel"] == variables["Channel"] &&
  455.                 aliases_data[alias_name]["specific"]["Proto"] == variables["Protocol"])
  456.             {
  457.                 switch (variables["Protocol"])
  458.                 {
  459.                     case "RubicsonStn":
  460.                     {   /* Add alias with these specifics: Channel=0,Proto=RubicsonStn,Address=<address of sensor> */
  461.                         /* if no Address is added to the alias, all RubicsonStn will match*/
  462.                         if (aliases_data[alias_name]["specific"]["Address"] == undefined)
  463.                         {
  464.                             if (pkt == 0)
  465.                             {
  466.                                 var last_value = {};
  467.                                 var last_value_string = Storage_GetParameter("LastValues", alias_name);
  468.  
  469.                                 if (last_value_string)
  470.                                 {
  471.                                     last_value = eval("(" + last_value_string + ")");
  472.                                 }
  473.                                 var timestamp = get_time();
  474.                                 last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  475.                                 last_value["Humidity_Percent"] = { "value" : humidity.toString(), "timestamp" : timestamp };
  476.                                 last_value["Wind_Speed_Avg"] = { "value" : windspeed_avg.toString(), "timestamp" : timestamp };
  477.                                 last_value["Wind_Speed_Max"] = { "value" : windspeed_max.toString(), "timestamp" : timestamp };
  478.                                 last_value["Wind_Direction"] = { "value" : winddirection.toString(), "timestamp" : timestamp };
  479.                                 last_value["Address"] = { "value" : addr, "timestamp" : timestamp };
  480.                                 Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  481.                                 RubicsonStationSuccessPkt1 = "RubicsonStnFound";
  482.                                 break loopAliases;
  483.                             } else
  484.                             {
  485.                               var last_value = {};
  486.                                 var last_value_string = Storage_GetParameter("LastValues", alias_name);
  487.  
  488.                                 if (last_value_string)
  489.                                 {
  490.                                     last_value = eval("(" + last_value_string + ")");
  491.                                 }
  492.                                 var timestamp = get_time();
  493.                                 last_value["WaterAbsolute_mm"] = { "value" : rain.toString(), "timestamp" : timestamp };
  494.                                 last_value["Battery_Low"] = { "value" : battery.toString(), "timestamp" : timestamp };
  495.                                 last_value["Address"] = { "value" : addr, "timestamp" : timestamp };
  496.                                 Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  497.                                 RubicsonStationSuccessPkt2 = "RubicsonStnFound";
  498.                                 break loopAliases;
  499.                             }
  500.                         }
  501.                         else if (addr == aliases_data[alias_name]["specific"]["Address"])
  502.                         {
  503.                             if (pkt == 0)
  504.                             {
  505.                                 var last_value = {};
  506.                                 var last_value_string = Storage_GetParameter("LastValues", alias_name);
  507.  
  508.                                 if (last_value_string)
  509.                                 {
  510.                                     last_value = eval("(" + last_value_string + ")");
  511.                                 }
  512.                                 var timestamp = get_time();
  513.                                 last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  514.                                 last_value["Humidity_Percent"] = { "value" : humidity.toString(), "timestamp" : timestamp };
  515.                                 last_value["Wind_Speed"] = { "value" : windspeed.toString(), "timestamp" : timestamp };
  516.                                 last_value["Wind_Direction"] = { "value" : winddirection.toString(), "timestamp" : timestamp };
  517.                                 last_value["Address"] = { "value" : addr, "timestamp" : timestamp };
  518.                                 Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  519.                                 RubicsonStationSuccessPkt1 = "RubicsonStnFound";
  520.                                 break loopAliases;
  521.                             } else
  522.                             {
  523.                               var last_value = {};
  524.                                 var last_value_string = Storage_GetParameter("LastValues", alias_name);
  525.  
  526.                                 if (last_value_string)
  527.                                 {
  528.                                     last_value = eval("(" + last_value_string + ")");
  529.                                 }
  530.                                 var timestamp = get_time();
  531.                                 last_value["WaterAbsolute_mm"] = { "value" : (rain*0.4).toString(), "timestamp" : timestamp };
  532.                                 last_value["Battery_Low"] = { "value" : battery.toString(), "timestamp" : timestamp };
  533.                                 last_value["Address"] = { "value" : addr, "timestamp" : timestamp };
  534.                                 Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  535.                                 RubicsonStationSuccessPkt2 = "RubicsonStnFound";
  536.                                 break loopAliases;
  537.                             }
  538.                         }
  539.                         break;
  540.                     }
  541.                     case "Viking":
  542.                     {   /* Add alias with these specifics: Channel=0,Proto=Viking,Address=<address of sensor> */
  543.                         if (type == 4)
  544.                         {
  545.                             if (crc != calccrc)
  546.                             {
  547.                                 Log("\033[31mError: VikingSensor, incorrect CRC, data="+data+", CRC="+crc+", calcCRC="+calccrc+"\033[0m");
  548.                                 break loopAliases;
  549.                             }
  550.                             if (addr == aliases_data[alias_name]["specific"]["Address"])
  551.                             {
  552.                                 VikingSuccess = "VikingFound";
  553.  
  554.                                 var last_value = {};
  555.                                 var last_value_string = Storage_GetParameter("LastValues", alias_name);
  556.  
  557.                                 if (last_value_string)
  558.                                 {
  559.                                     last_value = eval("(" + last_value_string + ")");
  560.                                 }
  561.  
  562.                                 var timestamp = get_time();
  563.                                 last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  564.                                 if (humidity<101)
  565.                                 {
  566.                                     last_value["Humidity_Percent"] = { "value" : humidity.toString(), "timestamp" : timestamp };
  567.                                 }
  568.  
  569.                                 Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  570.                                
  571.                                 break loopAliases;
  572.                             }
  573.                         }
  574.                         else if (type == 3)
  575.                         {
  576.                             /* Don't check crc since all bits did not fit in CAN-frame */
  577.                             if (addr == aliases_data[alias_name]["specific"]["Address"])
  578.                             {
  579.                                 VikingSuccess = "VikingFound";
  580.  
  581.                                 var last_value = {};
  582.                                 var last_value_string = Storage_GetParameter("LastValues", alias_name);
  583.  
  584.                                 if (last_value_string)
  585.                                 {
  586.                                     last_value = eval("(" + last_value_string + ")");
  587.                                 }
  588.  
  589.                                 var timestamp = get_time();
  590.                                 temp = temp-40.0;
  591.                                 waterlevel = (crc*256 + humidity)*0.3;
  592.                                 /* Using COUNTER as DS in rrdtool does only work if the data is integer,
  593.                                    to work around this let's create a second variable with the water level
  594.                                    multiplied with 10 and rounded to integer.
  595.                                    Then when generating graph, the data must be divided by 10 */
  596.                                 var waterlevel10xInt = Math.round(waterlevel*10);
  597.                                
  598.                                 last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  599.                                 last_value["WaterAbsolute_mm"] = { "value" : waterlevel.toString(), "timestamp" : timestamp };
  600.                                 last_value["WaterAbsolute10xInt_mm"] = { "value" : waterlevel10xInt.toString(), "timestamp" : timestamp };
  601.  
  602.                                 Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  603.                                
  604.                                 break loopAliases;
  605.                             }
  606.                         }
  607.                         break;
  608.                     }
  609.                     case "Rubicson":
  610.                     {   /* Add alias with these specifics: Channel=0,Proto=Rubicson,Address=<address of sensor> */
  611.                         /*if (crc != calccrc)
  612.                         {
  613.                             Log("\033[31mError: VikingSensor, incorrect CRC, data="+data+", CRC="+crc+", calcCRC="+calccrc+"\033[0m");
  614.                             break loopAliases;
  615.                         }*/
  616.                         if (addr == aliases_data[alias_name]["specific"]["Address"])
  617.                         {
  618.                             RubicsonSuccess = "RubicsonFound";
  619.  
  620.                             var last_value = {};
  621.                             var last_value_string = Storage_GetParameter("LastValues", alias_name);
  622.  
  623.                             if (last_value_string)
  624.                             {
  625.                                 last_value = eval("(" + last_value_string + ")");
  626.                             }
  627.  
  628.                             var timestamp = get_time();
  629.                             last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  630.                             /*if (humidity<101)
  631.                             {
  632.                                 last_value["Humidity_Percent"] = { "value" : humidity.toString(), "timestamp" : timestamp };
  633.                             }
  634.                             */
  635.                             Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  636.                            
  637.                             break loopAliases;
  638.                         }
  639.                         break;
  640.                     }
  641.                     case "VikingSteak":
  642.                     {   /* Add alias with these specifics: Channel=0,Proto=VikingSteak,Address=<address of sensor> */
  643.                         /* if no Address is added to the alias, all vikingSteaksensors will match*/
  644.                         if (aliases_data[alias_name]["specific"]["Address"] == undefined)
  645.                         {
  646.                             VikingSteakSuccess = "VikingFound";
  647.                             var last_value = {};
  648.                             var last_value_string = Storage_GetParameter("LastValues", alias_name);
  649.  
  650.                             if (last_value_string)
  651.                             {
  652.                                 last_value = eval("(" + last_value_string + ")");
  653.                             }
  654.  
  655.                             var timestamp = get_time();
  656.                             last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  657.                             last_value["Address"] = { "value" : addr, "timestamp" : timestamp };
  658.                             Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  659.                             break loopAliases;
  660.                         }
  661.                         else if (addr == aliases_data[alias_name]["specific"]["Address"])
  662.                         {
  663.                             VikingSteakSuccess = "VikingFound";
  664.                             var last_value = {};
  665.                             var last_value_string = Storage_GetParameter("LastValues", alias_name);
  666.  
  667.                             if (last_value_string)
  668.                             {
  669.                                 last_value = eval("(" + last_value_string + ")");
  670.                             }
  671.  
  672.                             var timestamp = get_time();
  673.                             last_value["Temperature_Celsius"] = { "value" : temp.toString(), "timestamp" : timestamp };
  674.                             last_value["Address"] = { "value" : addr, "timestamp" : timestamp };
  675.                             Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  676.                            
  677.                             break loopAliases;
  678.                         }
  679.                         break;
  680.                     }
  681.                     case "Nexa2":
  682.                     {   /* Add alias with these specifics: Channel=0,Proto=Nexa2,OnData=<data for on>,OffData=<data for off> */
  683.                         var deviceStateCommand = "";
  684.                         if (variables["IRdata"] == aliases_data[alias_name]["specific"]["OnData"] && variables["Status"] == "Pressed")
  685.                         {
  686.                             deviceStateCommand = "On";
  687.                         }
  688.                         else if (variables["IRdata"] == aliases_data[alias_name]["specific"]["OffData"] && variables["Status"] == "Pressed")
  689.                         {
  690.                             deviceStateCommand = "Off";
  691.                         }
  692.                         else
  693.                         {
  694.                             break;
  695.                         }
  696.                        
  697.                         var last_value = {};
  698.                         var last_value_string = Storage_GetParameter("LastValues", alias_name);
  699.  
  700.                         if (last_value_string)
  701.                         {
  702.                             last_value = eval("(" + last_value_string + ")");
  703.                         }
  704.                        
  705.                         if (( typeof(last_value["State"]) == "undefined" ) ||
  706.                             ( deviceStateCommand == "Off" && last_value["State"]["value"] == "On" ) ||
  707.                             ( deviceStateCommand == "On" && last_value["State"]["value"] == "Off" ))
  708.                         {
  709.                             last_value["State"] = { "value" : deviceStateCommand, "timestamp" : get_time() };
  710.  
  711.                             Storage_SetParameter("LastValues", alias_name, JSON.stringify(last_value));
  712.  
  713.                             /* Call any potential subscribers */
  714.                             if (Sensor_OnDeviceStateChangeFunctions[alias_name])
  715.                             {
  716.                                 for (var n in Sensor_OnDeviceStateChangeFunctions[alias_name])
  717.                                 {
  718.                                     /* Call callback with arguments alias, state */
  719.                                     Sensor_OnDeviceStateChangeFunctions[alias_name][n](alias_name, deviceStateCommand);
  720.                                 }
  721.                             }
  722.                         }
  723.                         break;
  724.                     }
  725.                 }
  726.             }
  727.         }
  728.         if (VikingSuccess == "VikingNotFound")
  729.         {
  730.             Log("Found unknown vikingsensor address="+addr+" temperature="+temp+" humidity="+humidity+" protocol type="+type);
  731.         }
  732.         if (VikingSteakSuccess == "VikingNotFound")
  733.         {
  734.             Log("Found unknown vikingSteaksensor address="+addr+" temperature="+temp);
  735.         }
  736.         if (RubicsonSuccess == "RubicsonNotFound")
  737.         {
  738.             Log("Found unknown Rubicson sensor address="+addr+" temperature="+temp);
  739.         }
  740.         if (OregonTempHumSuccess == "NotFound")
  741.         {
  742.             Log("Found unknown oregon temp/humidity sensor address="+addr+" temperature="+temp +" humidity="+humidity+" unknown="+unknown + " bat="+bat);
  743.         }
  744.         if (OregonRainSuccess == "NotFound")
  745.         {
  746.             Log("Found unknown oregon rain sensor address="+addr+" tot inch="+totInch +" totMM="+totMM+" inch/h="+inchPerHour + " mm/h="+mmPerHour +" bat="+bat);
  747.         }
  748.         if (OregonWindSuccess == "NotFound")
  749.         {
  750.             Log("Found unknown oregon wind sensor address="+addr+" Average="+average +" current="+current+" direction="+direction +" bat="+bat);
  751.         }
  752.         if (RubicsonStationSuccessPkt1 == "NotFound")
  753.         {
  754.             Log("Found unknown rubicson weather station, Packet 1 address="+addr + " temperature="+temp + " humidity="+humidity+" WindSpeed="+windspeed + " WindDirection="+winddirection);
  755.         }
  756.         if (RubicsonStationSuccessPkt2 == "NotFound")
  757.         {
  758.             Log("Found unknown rubicson weather station, Packet 2 address="+addr + " Rain="+rain + "mm BatteryLow="+battery);
  759.         }
  760.     }
  761. }
  762. Module_RegisterToOnMessage("all", SensorRf_OnMessage);
  763.  
  764. function Sensor_StoreNumberInPhonebook(number, timestamp)
  765. {
  766.   var phonebookNumbers = Storage_GetJsonParamter("PhoneBook", number);
  767.  
  768.   if (!phonebookNumbers)
  769.   {
  770.     phonebookNumbers = [];
  771.  
  772.     url = "wap.eniro.se/query?search_word=" + number + "&what=mobwp";
  773.     //Log("\033[31mURL: http://"+url+"\033[0m\n");
  774.  
  775.     Http_Request(url, function(socket_id, result, header, content_data)
  776.     {
  777.       //Log("\033[31mOnlinePhonebook-eniro: result was: " + result + "\033[0m\n");
  778.       //Log("\033[31mOnlinePhonebook-eniro: content was: " + content_data + "\033[0m\n");
  779.  
  780.       if (result.indexOf("200 OK") != -1)
  781.       {
  782.  
  783.         var lines = content_data.split("\n");
  784.  
  785.         var endString = "<anchor>Tillbaka<prev/></anchor>";
  786.         var nameStartString = "<td class=\"hTd2\">";
  787.         var nameEndString = "</table>";
  788.  
  789.         for (var n = 1; n < lines.length; n++)
  790.         {
  791.           var line = lines[n].trim("\n");
  792.  
  793.           if (line.indexOf(endString) != -1)
  794.           {
  795.             break;
  796.           }
  797.  
  798.           if (line.indexOf(nameStartString) != -1)
  799.           {
  800.             line = lines[n + 1].trim("\n");
  801.             splitted = line.split("b>");
  802.  
  803.             phonebookNumbers.push(splitted[1].substr(0, splitted[1].length - 2));
  804.             break;
  805.           }
  806.         }
  807.  
  808.         //Log("\033[31mOnlinePhonebook: Line: " + lines[1] + "\033[0m\n");
  809.         //Log("\033[31mOnlinePhonebook: Line: " + lines[2] + "\033[0m\n");
  810.         //Log("\033[31mOnlinePhonebook: Line: " + lines[3] + "\033[0m\n");
  811.         if (phonebookNumbers.length > 0)
  812.         {
  813.           Storage_SetJsonParameter("PhoneBook", number, phonebookNumbers);
  814.  
  815.           Sensor_UpdateNameInPhonecalls(timestamp, phonebookNumbers);
  816.  
  817.           Log("\033[31mOnlinePhonebook-eniro: Found: " + JSON.stringify(phonebookNumbers) + "\033[0m\n");
  818.         }
  819.       }
  820.       else
  821.       {
  822.         Log("\033[31mOnlinePhonebook-eniro: Failed to do name lookup, result was: " + result + "\033[0m\n");
  823.       }
  824.  
  825.       if (phonebookNumbers.length == 0)
  826.       {
  827.         if (typeof sensorRKSEEK_API !== 'undefined')
  828.         {
  829.           url = "rkseek.oblivioncreations.se/?client="+sensorRKSEEK_API+"&n=" + number + "&out=text";
  830.           Log("\033[31mURL: http://"+url+"\033[0m\n");
  831.  
  832.           Http_Request(url, function(socket_id, result, header, content_data)
  833.           {
  834.             phonebookNumbers = [];
  835.  
  836.             if (result.indexOf("200 OK") != -1)
  837.             {
  838.               //Log("\033[31mOnlinePhonebook: result was: " + content_data + "\033[0m\n");
  839.               var lines = content_data.split("\n");
  840.               //Log("\033[31mOnlinePhonebook: Line: " + lines[1] + "\033[0m\n");
  841.               //Log("\033[31mOnlinePhonebook: Line: " + lines[2] + "\033[0m\n");
  842.               //Log("\033[31mOnlinePhonebook: Line: " + lines[3] + "\033[0m\n");
  843.               if (lines[2].length > 0)
  844.               {
  845.                 phonebookNumbers = [ lines[2] ]; // TODO Is this really correct?!
  846.                 Storage_SetJsonParameter("PhoneBook", number, phonebookNumbers);
  847.                
  848.                 Sensor_UpdateNameInPhonecalls(timestamp, phonebookNumbers);
  849.  
  850.                 Log("\033[31mOnlinePhonebook-rseek: Found: " + JSON.stringify(phonebookNumbers) + "\033[0m\n");
  851.               }
  852.             }
  853.             else
  854.             {
  855.               Log("\033[31mOnlinePhonebook-rseek: Failed to do name lookup, result was: " + result + "\033[0m\n");
  856.             }
  857.           });
  858.         }
  859.       }
  860.     });
  861.         /*
  862.         Http_Request("wap.hitta.se/default.aspx?Who=" + number + "&Where=&PageAction=White",
  863.             function(socket_id, result, header, content_data) {
  864.                 var persons = new Array();
  865.                 if (result.indexOf("200 OK") != -1)
  866.                 {
  867.                     var endString = "<anchor>Tillbaka<prev/></anchor>";
  868.                     var nameStartString = " title=\"Link\">";
  869.                     var nameEndString = "</a>";
  870.  
  871.                     var lines = content_data.split("<br/>");
  872.  
  873.                     for (var n = 1; n < lines.length; n++)
  874.                     {
  875.                         var line = lines[n].trim(" \n");
  876.  
  877.                         if (line.indexOf(endString) != -1)
  878.                         {
  879.                             break;
  880.                         }
  881.                         var pos = line.indexOf(nameStartString + (persons.length+1) + ".");
  882.  
  883.                         if (pos != -1)
  884.                         {
  885.                             pos += nameStartString.length + 2
  886.                             persons[persons.length] = line.substr(pos, line.length-pos-nameEndString.length).html_entity_decode().replace("  ", " ");
  887.                         }
  888.                     }
  889.                     if (persons.length > 0) {
  890.                         Storage_SetJsonParameter("PhoneBook", number, persons);
  891.  
  892.                         //CAll all listeners!
  893.                         //....
  894.  
  895.                         Log("\033[31mOnlinePhonebook: Found: " + JSON.stringify(persons) + "\033[0m\n");
  896.                     }
  897.                 }
  898.                 else
  899.                 {
  900.                     Log("\033[31mOnlinePhonebook: Failed to do name lookup, result was: " + result + "\033[0m\n");
  901.                 }
  902.             }
  903.         );
  904.         */
  905.  
  906.   }
  907.   else
  908.   {
  909.     //Log("Number already stored\n");
  910.  
  911.     Sensor_UpdateNameInPhonecalls(timestamp, phonebookNumbers);
  912.   }
  913.  
  914.   return phonebookNumbers;
  915. }
  916. Console_RegisterCommand(Sensor_StoreNumberInPhonebook, function(arg_index, args) { return Console_StandardAutocomplete(arg_index, args); });
  917.  
  918. function Sensor_StoreNumberInPhonebookManual(number, name)
  919. {
  920.     if (arguments.length < 2)
  921.     {
  922.         Log("\033[31mNot enough parameters given.\033[0m\n");
  923.         return false;
  924.     }
  925.    
  926.     var completename = arguments[1];
  927.     for (var i=2; i<arguments.length; i++)
  928.     {
  929.         completename = completename+" "+arguments[i];
  930.     }
  931.    
  932.     phonebookNumbers = [];
  933.     phonebookNumbers.push(completename);
  934.     Storage_SetJsonParameter("PhoneBook", number, phonebookNumbers);
  935. }
  936. Console_RegisterCommand(Sensor_StoreNumberInPhonebookManual, function(arg_index, args) { return Console_StandardAutocomplete(arg_index, args); });
  937.  
  938. function Sensor_UpdateNameInPhonecalls(timestamp, numbers)
  939. {
  940.   if (numbers.length > 0)
  941.   {
  942.     var lastValueString = Storage_GetParameter("PhoneCalls", timestamp);
  943.  
  944.     if (lastValueString)
  945.     {
  946.       var lastValue = JSON.parse(lastValueString);
  947.  
  948.       lastValue.names = numbers;
  949.  
  950.       Storage_SetParameter("PhoneCalls", timestamp, JSON.stringify(lastValue));
  951.     }
  952.   }
  953. }
  954.  
  955. function Sensor_SetUltrasonicMode(alias_name, BottomLimit, TopLimit, mode)
  956. {
  957.     if (arguments.length < 4)
  958.     {
  959.         Log("\033[31mNot enough parameters given.\033[0m\n");
  960.         return false;
  961.     }
  962.  
  963.     var aliases_data = Module_ResolveAlias(alias_name, Sensor_ModuleNames);
  964.     var found = false;
  965.  
  966.     for (var name in aliases_data)
  967.     {
  968.         var variables = {   "0Percent"     : BottomLimit,
  969.                     "100Percent"   : TopLimit,
  970.                     "SensorMode"   : mode,
  971.                     "SensorId"  : aliases_data[name]["specific"]["Channel"],
  972.         };
  973.         if (Module_SendMessage(aliases_data[name]["module_name"], aliases_data[name]["module_id"], "UltrasonicConfig", variables))
  974.         {
  975.             Log("\033[32mCommand sent successfully to " + name + ".\033[0m\n");
  976.         }
  977.         else
  978.         {
  979.             Log("\033[31mFailed to send command to " + name + ".\033[0m\n");
  980.         }
  981.  
  982.         found = true;
  983.     }
  984.  
  985.     if (!found)
  986.     {
  987.         Log("\033[31mNo aliases by the name " + alias_name + " were applicable for this command.\033[0m\n");
  988.         return false;
  989.     }
  990.  
  991.     return true;
  992. }
  993. Console_RegisterCommand(Sensor_SetUltrasonicMode, function(arg_index, args) { return Console_StandardAutocomplete(arg_index, args, Sensor_Aliases()); });
  994.