Universal gateway for 315/433Mhz devices



  • Hallo everybody!
    I've recently come by, through Radio Shack closing and an Amazon sale, 3 sets of SecureSam wireless security sensors (5 door/window open and 1 PIR motion each) and 6 433Mhz remote controlled outlets. I had a couple odd 315/433Mhz sensors added individually already, but now I'm feeling like there's got to be an easier way.
    My goal is to make a MySensors device with both a transmitter and receiver which simply forwards all received (valid) codes straight to OpenHAB without having to have them pre-programmed and allow OpenHAB to send codes which the node then blindly transmits. This way, new devices can be added within the rules and items definitions without having to reprogram the radio node.
    I'm using the V_VAR1 data type and seemingly have come up with a node sketch which successfully sends the received code to the gateway.

    /*
     MySensors node sketch for adding 315/433Mhz radios to OpenHAB transparently
    */
    
    #include <RCSwitch.h>
    #include <MySensor.h>
    #include <SPI.h>
    #define NODE_ID 105
    MySensor gw;
    #define CHILD_ID_CODE 0
    unsigned long readwait = 1000; //time to wait before transmitting the same code again
    unsigned long lastread = 0;  //last millis() value code was read
    long lastcode;  //store last transmitted code
    
    RCSwitch mySwitch = RCSwitch();
    MyMessage msgCode(CHILD_ID_CODE, V_VAR1);  //using VAR1 data type (24) lacking a better option for passing a string to the gateway
    
    void setup() {
      mySwitch.enableReceive(1);  // Receiver on inerrupt 1 => that is pin #3
      // Initialize library and add callback for incoming messages
      gw.begin(incomingMessage, NODE_ID, true);
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("ASK Transmit/Receive", "1.0");
      //Register to gateway
      gw.present(CHILD_ID_CODE, S_CUSTOM);
      
      //315MHz radio initialize  
     // Transmitter is connected to Arduino Pin #7  
      mySwitch.enableTransmit(7);
    
      // Optional set pulse length.
      mySwitch.setPulseLength(200);
      
      // Optional set protocol (default is 1, will work for most outlets)
       mySwitch.setProtocol(1);
      
      // Optional set number of transmission repetitions.
      mySwitch.setRepeatTransmit(2);
    }
    
    void loop() {
      gw.process();
      if (mySwitch.available()) {
        
        int value = mySwitch.getReceivedValue(); //used by check function
        long code = mySwitch.getReceivedValue(); //int value doesn't end up containing the code so we read it again into a long
        
        //Make sure we don't spam the gateway for devices which transmit multiple times per trigger
        //Allow unique IDs through even if the wait isn't over so we don't miss out on other devices
        if ((lastread + readwait) <= millis() || lastcode != code) {
        if (value == 0) {
          Serial.print("Unknown encoding");
        } else {
          Serial.print("Received ");
          Serial.print( mySwitch.getReceivedValue() );
          Serial.print(" / ");
          Serial.print( mySwitch.getReceivedBitlength() );
          Serial.print("bit ");
          Serial.print("Protocol: ");
          Serial.println( mySwitch.getReceivedProtocol() );
          Serial.print("Time: ");
          Serial.println(millis()); //watch the time between retransmits to fine-tune the wait value
          gw.send(msgCode.set(code)); //send the successfully read code to the gateway
          lastread = millis(); //reset last read time
          lastcode = code; //store last code
        }
        }
        mySwitch.resetAvailable();
      }
    }
    
    void incomingMessage(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_VAR1) {
         // Transmit code
         mySwitch.send(message.sensor, 24);
         // Write some debug info
         Serial.print("Incoming code to transmit:");
         Serial.print(message.sensor);
       } 
    }
    

    My problem now is that I can't quite wrap my head around getting OpenHAB to read the strings and do something. I'm using TimO's tutorial for serial gateway and a hash map for my various nodes. The initial plan was to use something like that to map a code to an item, but my rule-fu is still weak and I'm not having much luck adapting that tutorial to this. I've got my table for mapping a code to an item:

    var HashMap<String, String> CodeToItemsMap = NewLinkedHashMap(
        "7793834;"		-> "Laundry_Room_PIR",
        "Laundry_Room_PIR"	-> "7793834;",
        "4555512;"		-> "2_outlet_ON",
        "2_outlet_ON"	-> "4555512;",
        "4541876;"		-> "2_outlet_OFF",
        "2_outlet_OFF"	-> "4541876;",
        "6710453;"		-> "Front_Door_Trip",
        "Front_Door_Trip"	-> "6710453;",
    

    and I'm guessing I need to make a new "IF" statement under the V_DIMMER and V_LIGHT ones

    if (subType == V_VAR1){
                        postUpdate(CodeToItemsMap.get( nodeId + ";" + childId + ";"), msg)
                        println ("Dimmer item: " + CodeToItemsMap.get( nodeId + ";" + childId + ";") + " Dimmer: " + msg )
                            }
    

    But I'm not having good luck finding a good how-to for the syntax here and every time I futz it up I have to wait 2 solid minutes for my RaspberryPi to reload my rules, so I figured I'd see if anyone has any input.
    Am I over(or under)thinking this and there's a simple solution? Seemingly this could be a handy addition to both MySensors and OpenHAB since it would make adding the thousands of readily/cheaply available switched outlets and basic wireless home security devices already on the market nearly effortless.
    Thanks in advance for any help I can get, or even a referral in the right direction!



  • Ok, so I've made some more progress. I'm not much of a programmer, so I didn't realize that HashMap was a java thing and not an OpenHAB thing. After a couple quick tutorials I've got this:

    var HashMap<String, String> CodeToItemsMap = NewLinkedHashMap(
        "7793834;"      -> "Laundry_Room_PIR",
        "Laundry_Room_PIR"  -> "7793834;",
        "4555512;"      -> "2_outlet_ON",
        "2_outlet_ON"   -> "4555512;",
        "4541876;"      -> "2_outlet_OFF",
        "2_outlet_OFF"  -> "4541876;",
        "6710453;"      -> "Front_Door_Trip",
        "Front_Door_Trip"   -> "6710453;",
    
    var HashMap<String, String> CodeToActionMap = newLinkedHashMap(
        "4555512;"		-> "ON",
        "ON"		-> "4555512;",
        "4541876;"		-> "OFF",
        "OFF"		-> "4541876;",
        "6710453;"		-> "OPEN",
        "OPEN"		-> "6710453;",
    
    if (subType == V_VAR1){
                        println (msg)
    		    postUpdate(CodeToItemsMap.get( msg + ";"), CodeToActionMap.get( msg + ";"))
                        println ("Item updated: " + CodeToItemsMap.get( msg + ";") + " State: " + CodeToActionMap.get( msg + ";") )
                            }
    
    

    This works! The couple codes I've added to my hashmap update the appropriate items despite not being programmed into the MySensors node at all. Keys that haven't been added don't really do anything. OpenHAB shows an error about "Null" not existing, which I assume is the code not being in the map, but it doesn't seem to be harmful so I don't necessarily see a need to do anything about that.
    New problem, though. I can only have one of each type of sensor in the action map or I get an error upon reloading the rules file to the effect "duplicate key". Eg, can't have more than one code resolve to "Open" or "ON". I believe there's a java method for multi-key mapping, so I guess I'll work on that. I'll keep posting with progress, though I'd love some feedback, so at least there's an archive of this so maybe it'll help someone at some point if I actually get it figured out!



  • Is there anyway to use directly 433 with openhab --- serial gateway will be 433 receiver and transmitter (without mysensors lib and devices)

    @static418 Thank you for your idea.

    Create 2 maps, if one is null then get other map.

    I removed ";" things because i dont need them.

    var HashMap<String, String> CodeToItemsMapOn = newLinkedHashMap(
        "14013452"->"SOKET_1",
        "SOKET_1"->"14013452" 
        )
        var HashMap<String, String> CodeToItemsMapOff = newLinkedHashMap(
    	"14013443"->"SOKET_1",
        "SOKET_1"->"14013443"
        )			
    var HashMap<String, String> CodeToActionMap = newLinkedHashMap( //nothing important because there is no duplicate
        "14013452"->"ON",
        "ON"->"14013452",
        "14013443"->"OFF",
        "OFF"->"14013443"
        )  
    //remember hashmaps must be out of the rule
    rule "Arduino sends to Openhab"
        when
            Item Arduino received update
        then
    .........
    	if(subType==V_VAR1){
    		var myOrder=CodeToItemsMapOn.get(msg) //1.map
    		if(myOrder==null){myOrder=CodeToItemsMapOff.get(msg)} //2.map
    		
    		postUpdate(myOrder,CodeToActionMap.get(msg)) //make you job
    	}
    .......
    end
    

    This code is only for updating the openhab screen (receiving), i will work for transmit.

    You can find more on https://github.com/openhab/openhab/wiki/Taking-Rules-to-New-Heights

    There is another problem with CodeToActionMap; If i got a lot of outlets this means many on and off commands ..

    rule "MY ON"
    	when
    		Item SOKET_1 received command ON
    	then
    				sendCommand(Arduino, "105;105;1;0;24;" + 14013452  + "\n")
    	end
    	
    rule "MY OFF"
    	when
    		Item SOKET_1 received command OFF
    	then
    				sendCommand(Arduino, "105;0;1;0;24;" + 14013443 + "\n")
    	end`
    

    These rules for TRANSMIT didnt work any idea???



  • @C.r.a.z.y.
    I'm sure there's a way to use it without the MySensors stuff, but that's a little bit out of my scope. I'd imagine it would just involve writing up an Arduino sketch for a device with a 433Mhz transmitter and receiver and have it listen for serial commands. OpenHAB can send whatever you want to serial.
    As for transmitting, it seems to work with the arduino sketch I posted earlier, but I still need to put some kind of protection in place to prevent a feedback loop since it also listens for codes. When I make it transmit, it gets stuck sending and receiving the same code to itself.
    A basic example of testing the transmit (I'd unplug the receiver if you haven't fixed the loop issue) would be:

    rule "two-outlet ON update"
    
    when Item two_outlet_ON received update
    	if(two_outlet_ON.state==ON) {
    		sendCommand(Arduino, "105;0;1;0;24;" + CodeToItemsMap.get("two_Outlet_ON") + "\n")
           		OUTLET1.state = ON
    }
    end
    

    This isn't as clean as I'd like, since I'm still basically defining the command with the exception of the code itself. But it does work!



Suggested Topics

21
Online

11.2k
Users

11.1k
Topics

112.5k
Posts