This is the forum archive of Homey. For more information about Homey, visit the Official Homey website.

The Homey Community has been moved to https://community.athom.com.

This forum is now read-only for archive purposes.
RF-433

Creating an app to replace my 433MHz remote for dual relay controller

DIYglennDIYglenn Member
edited April 2018 in Developers
I got a simple $6 dual relay controller, set to switch between two relays (latching) so that it controls a linear actuator. 
Now, this is what I ordered, but it isn't exactly the same, but in short there are a bunch of these on eBay, pretty much the same thing all of them, and at least mine is using the chip "SYN470R" on the 433MHz board.



This is what I got:



Anyways, my actual question is HOW can I get this talking to Homey? Maybe I should've used Arduino/Wemos and MQTT with a dual relay board instead, but I'm up for a challenge, I want to learn something.

I got everything working, I just want that remote to be on the balcony where the window is, and automate the closing/opening with Homey.

I was hoping I'd be able to add this from any of the existing apps, but I guess not. 

I'd be happy to contribute and make an app for it, but I need some help to be pushed in the right direction.

Do I need a logic analyzer?
Can Homey's signal recording be enough?
There's a learn button, will Homey have to be connected to it in "learn" mode?
Will the signal still always be the same code?
Do I add support for the remote or the board?

There's probably a lot of uses for controllers like these, even though they're not "rolling code" and therefore not safe, but for greenhouses etc. they are of excellent value.

I appreciate any help I can get. The balcony gets really hot now that the sun is back after the winter, so I would love a way to open the window automatically based on temperature and wind/rain conditions. 
Tagged:
«1

Comments

  • DIYglennDIYglenn Member
    edited April 2018
    Thanks. I find it a bit hard still though, I'm not sure exactly what values I'm looking for, or how to convert the signal to integer or binary.

    I used the signal tool and held the lock button, and then recorded again when I held unlock and now got two VCD files (the remote repeats the signal as long as it is held).

    I then opened GTKwave and can now see a pattern. I'm not familiar with GTKwave at all, so I don't know how to get both signals in the same window to compare, I now only have one signal and have to open two tabs to compare them.

    Where do I go from here? Is there a way to mark the signal and convert to something Homey can use?

    Lock:

    Unlock:


    Thanks!

    Edit:
    I guess I'm mixing two different methods here... I'm now following the guide you linked to more thoroughly, the signal seems to be a really simple one, but it's all new to me here... 
  • Now you're mixing two methods up. In chrome-browser, login to your Homey and then do a record. We did this in a slack-session step by step once too:
    https://forum.athom.com/uploads/editor/az/eztw1rmmuuap.pdf
    also, I think https://github.com/athombv/node-homey-433/wiki/How-to-record-a-signal is easier to read :)

  • So I used the method you linked to, and while it seemed harder to begin with (compared to clicking a button), this gives me a perfectly sorted list instead.

    (Are they (Athom) really going to remove the Mac/PC app?! I don't like the new iPhone app, but a potential iPad app is welcome, but only in addition to an app I can use on my Mac... The developer console is great!)

    At first I didn't get one that stood out from the rest, (1-3 on all) or I would get two with equal numbers (44), but sometimes I would get one with 80 or more (number 50). I did it several times to be sure.

    Now.. The numbers aren't perfectly matching, so now I'm over to the part about creating an average. A lot for a newbie here, but I can see that it's maybe easier to get the information I'm looking for this way

    I'm posting my results so it might help others know what they are looking for (I've tried formatting it to be more readable)

    recordData.reduce((lengths, recordEntry) => Object.assign(lengths, { [recordEntry.length]: (lengths[recordEntry.length] || 0) + 1 }), {});
    Object {32: 1, 33: 2, 34: 1, 48: 4, 49: 3, 50: 86, 51: 1, 52: 20, 53: 1, 54: 2, 55: 1, 56: 4, 58: 1, 62: 2, 63: 1, 65: 1, 66: 1, 68: 2, 70: 1, 71: 2, 74: 2, 75: 1, 76: 2, 80: 1, 81: 1, 89: 1, 97: 1, 116: 1, 145: 1} 32: 1 33: 2 34: 1 48: 4 49: 3 50: 86 51: 1 52: 20 53: 1 54: 2 55: 1 56: 4 58: 1 62: 2 63: 1 65: 1 66: 1 68: 2 70: 1 71: 2 74: 2 75: 1 76: 2 80: 1 81: 1 89: 1 97: 1 116: 1 145: 1 __proto__: Object
    var fl = 50; recordData = recordData.filter(recordEntry => recordEntry.length === fl)
    (86) [Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50), Array(50)] 0: Array(50) 0: 1380 1: 474 2: 438 3: 1326 4: 444 5: 1319 6: 456 7: 1313 8: 462 9: 1302 10: 1384 11: 436 12: 1392 13: 437 14: 1382 15: 436 16: 1388 17: 433 18: 1385 19: 434 20: 1385 21: 436 22: 464 23: 1303 24: 471 25: 1302 26: 464 27: 1312 28: 1384 29: 433 30: 464 31: 1313 32: 455 33: 1307 34: 471 35: 1307 36: 464 37: 1302 38: 459 39: 1314 40: 466 41: 1306 42: 461 43: 1306 44: 464 45: 1312 46: 1386 47: 437 48: 454 49: 3828 length: 50 __proto__: Array(0) 1: Array(50) 0: 1386 1: 475 2: 435 3: 1328 4: 449 5: 1319 6: 452 7: 1317 8: 462 9: 1303 10: 1392 11: 437 12: 1378 13: 441 14: 1382 15: 443 16: 1381 17: 442 18: 1381 19: 441 20: 1387 21: 436 22: 464 23: 1312 24: 461 25: 1311 26: 454 27: 1317 28: 1381 29: 437 30: 467 31: 1310 32: 458 33: 1309 34: 463 35: 1312 36: 465 37: 1312 38: 461 39: 1312 40: 457 41: 1310 42: 458 43: 1320 44: 452 45: 1321 46: 1383 47: 437 48: 465 49: 3858 length: 50 __proto__: Array(0) 2: Array(50) 0: 1376 1: 468 2: 435 3: 1341 4: 440 5: 1321 6: 455 7: 1311 8: 463 9: 1314 10: 1383 11: 436 12: 1387 13: 441 14: 1384 15: 444 16: 1385 17: 434 18: 1387 19: 441 20: 1386 21: 437 22: 454 23: 1321 24: 455 25: 1316 26: 458 27: 1310 28: 1386 29: 447 30: 456 31: 1308 32: 469 33: 1310 34: 465 35: 1309 36: 457 37: 1314 38: 460 39: 1307 40: 469 41: 1311 42: 457 43: 1317 44: 454 45: 1311 46: 1388 47: 445 48: 457 49: 3846 length: 50 __proto__: Array(0) 3: Array(50) ...
  • Well, that seems like a fairly simple signal with something like [434,1380] as one bit and [1380,434] as the other.
    You can discect the Start Of Signal and End Of Signal and calculate the average (better) values of 434 and 1380 in the bits. Then you also have the signal send.
  • Out from my previous post, I can't see any SOF, but is 49 considered EOF or a word?
  • I think it will be [457, 3846]. Assuming the values of 46 and 47 will lead to a bit [1388,445]
  • DIYglennDIYglenn Member
    edited April 2018
    Thanks for your help, and sorry for not replying back earlier.

    I'll see if I can work my brain around this. Coding is new for me, not to mention decoding 433MHz signals.

    One question though; What do you mean when you say that the values "will lead to a bit"? 
    Edit:
    Oh, that the previous two are considered a word, and are not together with EOF?

    How do I know if my signal has SOF and EOF? The high end value makes me think, as your suggestion, that it is [456,3846], but what about SOF? There doesn't seem to be any definite value there.
  • DIYglennDIYglenn Member
    edited April 2018
    ...So my signal only has two words? Why are there 50 signals then?
    I'm not sure I get how to convert this to anything useful, what exactly does it mean if something can be "parsed" or not?
    (Reading the PDF)
  • DIYglennDIYglenn Member
    edited April 2018
    I didn't know what to write as SOF, as it is the same as one of the words, but it's still only once at the beginning, so I guess that is a SOF signal?...

    So I set SOF and EOF to "2" and then "predictedWords" as follows:
    var predictedWords = [[400, 1300], [1300, 400]]; var tolerance = 100;

    Does this seem correct?

    I now have this:

    {
    "sof": [
    1408,
    546
    ],
    "eof": [
    464,
    3875
    ],
    "words": [
    [
    462,
    1322
    ],
    [
    1393,
    442
    ]
    ],
    "interval": 10000,
    "sensitivity": 0.7,
    "repetitions": 20,
    "minimalLength": 23,
    "maximalLength": 23
    }

    Does this make sense from the data I provided earlier?

    If so, should it now be repeated for the next button on the remote...?

  • bvdbosbvdbos Member
    edited April 2018
    I think your SOF might be empty. Then you have 48 values which leads to 24 bits/words. These are three bytes of eight. EOF seems correct...
  • DIYglennDIYglenn Member
    edited April 2018
    Thanks! That seems more correct. 
    This means than words should be defined the other way around? Or doesn't it matter? I mean, it starts with number [1408, 546] so this would be word1? And [462, 1322] would be word2? Does this order matter? I guess otherwise it would invert 1 and 0?

    For some reason, the first one does have a higher average on both values, but I do agree that it still doesn't make sense to have it set as SOF.

    So what will the next step be? 
    Should I use the 433MHz app generator?
  • Damn... Went to redo this, start over again, but now the scripts doesn't work...
    /api/manager/microcontroller/record?_=1523900784873 Failed to load resource: the server responded with a status of 500 (Internal Server Error)


  • Fixed by pulling power, reboot did not fix it.
  • New data:
    {
    	"sof": [],
    	"eof": [
    		465,
    		3859
    	],
    	"words": [
    		[
    			1396,
    			438
    		],
    		[
    			463,
    			1304
    		]
    	],
    	"interval": 10000,
    	"sensitivity": 0.7,
    	"repetitions": 20,
    	"minimalLength": 24,
    	"maximalLength": 24
    }
  • DIYglennDIYglenn Member
    edited April 2018
    Sorry for spamming my thoughts out on this forum. 
    Does the above data make sense?
    as there probably is no SOF for this device, it starts high and goes low, should this be considered the first word like above?

    From the example text, [110, 1100] , [1100, 110] seems to be typical for the two words, but mine are opposite, the first starting high. 
    Does this mean that my device starts with the binary value 1?

    Where does the button value appear in all this? There is a lock and unlock button. 
    How about pairing?

    Are there any functioning safety measures at all, or can “anyone” just send this signal and open my window?

     I’m not concerned about safety on this particular installation, because it doesn’t matter for my house safety, but IF I were to use something similar on a window in the house, could that be hacked?
  • DIYglennDIYglenn Member
    edited April 2018
    Ran 
    athom app create
    And then opened that folder and ran
    homey433 generate
    This gave me this error about a folder not existing
    Error: /Users/.../433_generator
    I created that folder, but this gave me a new error:
    Error: Cannot find module '/Users/.../433_generator/config.js'
    I created that file (an empty one), then ran the command as "sudo" and it went through, but this doesn't seem correct...

    Should the folder and config be generated automatically?


    Would love if someone could help me further.
    I'm considering doing a write-up afterwards for people like me - that aren't developers, but still like to utilize the tools created, and use Homey to learn.
  • Anyone guys? 

    Where do I go from here? Devs?

    RFDriver, 433MHz app generator? Are any of these two still usable, or should everything be made from scratch?

    I don't get it...
  • I would try starting with https://github.com/BasKiers/com.a.doorbell and put your values in the app.

  • bvdbos said:
    I would try starting with https://github.com/BasKiers/com.a.doorbell and put your values in the app.

    Thanks!
    But that app seems to be built from the generator as well?

    I’ll try to work my way through it. 
  • DIYglenn said:
    Ran 
    athom app create
    And then opened that folder and ran
    homey433 generate
    This gave me this error about a folder not existing
    Error: /Users/.../433_generator
    I created that folder, but this gave me a new error:
    Error: Cannot find module '/Users/.../433_generator/config.js'
    I created that file (an empty one), then ran the command as "sudo" and it went through, but this doesn't seem correct...

    Should the folder and config be generated automatically?


    Would love if someone could help me further.
    I'm considering doing a write-up afterwards for people like me - that aren't developers, but still like to utilize the tools created, and use Homey to learn.
    I opened an issue on github, and got a response that the folder has to be created manually. Also, RFdriver seems to be the way to go:

    The 433_generator folder should be manually created as its contents describe the workings of the app it should generate. However, we are currently phasing out the 433 generator and its support in favor of the SDKv2 successor https://github.com/athombv/node-homey-rfdriver

  • I forked the doorbell app. I changed the values inn app.json and 433generator config to what I've recorded earlier.

    I now tried running with "athom app run", but get this:
    ✓ Validating app...
    ✘ Homey App did not validate against level `debug`:
    Invalid signal: 433.aDoorbell
    invalid_sensitivity
    Not installing, please fix the validation issues first
    Glenns-MacBook-Air:com.wordpress.diyglenn glenn$ 

  • I downloaded the app I forked from without editing anything, and I still get the same problem?!
  • JPeJPe Member
    seems something with the Sensitivity, maybe if you use  "sensitivity": 0.5,  it will go?
  • DIYglennDIYglenn Member
    edited May 2018
    JPe said:
    seems something with the Sensitivity, maybe if you use  "sensitivity": 0.5,  it will go?
    Spot on! 
    Changed to 0.5 and it worked immediately. 

    I'm not quite sure where to go from here though, the app is installed, and I tried the pairing wizard. Clicking the button did give me a binary code in the terminal window, both for lock and unlock button. The only difference was "0" and "1" at the end. And sometimes the first number was 0 instead of 1, which seems to be incorrect.
    The pairing wizard didn't go further though, so I couldn't add the device. 

    Is this what it reads from the key, or is it using what I defined as SOF/EOF/Words? 

    I'm still a bit unsure about my words, as it seems like most of these things has the first word with a low to high value, f.ex. [100, 1000] while mine is opposite. I don't know if this matters.

    {
    	"sof": [],
    	"eof": [
    		465,
    		3859
    	],
    	"words": [
    		[
    			1396,
    			438
    		],
    		[
    			463,
    			1304
    		]
    	],
    	"interval": 10000,
    	"sensitivity": 0.7,
    	"repetitions": 20,
    	"minimalLength": 24,
    	"maximalLength": 24
    }
  • JPeJPe Member
    in  \433_generator\drivers\doorbell.js  you need to specify the part of  "Payload" that you want to use, see :

    payloadToData(payload) { // Convert received data to usable variables
    if (payload.length === 17) {
    const data = {
    address: this.bitArrayToString(payload.slice(1, 17)),
    state: payload[1], // This is just a guesstimated bit since I do not own such a doorbell
    };
    data.id = data.address;
    return data;
    }
    return null;
    }

    dataToPayload(data) { // Convert a data object to a bit array to be send
    if (
    data &&
    data.address && data.address.length === 16 &&
    typeof data.state !== 'undefined'
    ) {
    const address = this.bitStringToBitArray(data.address);
    return [Number(data.state)].concat(address);
    }
    return null; 
  • JPe said:
    in  \433_generator\drivers\doorbell.js  you need to specify the part of  "Payload" that you want to use, see :

    payloadToData(payload) { // Convert received data to usable variables
    if (payload.length === 17) {
    const data = {
    address: this.bitArrayToString(payload.slice(1, 17)),
    state: payload[1], // This is just a guesstimated bit since I do not own such a doorbell
    };
    data.id = data.address;
    return data;
    }
    return null;
    }

    dataToPayload(data) { // Convert a data object to a bit array to be send
    if (
    data &&
    data.address && data.address.length === 16 &&
    typeof data.state !== 'undefined'
    ) {
    const address = this.bitStringToBitArray(data.address);
    return [Number(data.state)].concat(address);
    }
    return null; 
    Thanks! 
    So my payload is 24 here? 
    Do I write payload.length === 24?

    Not sure about that "slice" part. 

    I guess this is to "skip" the first 23 numbers and only focus on the "1" and "0" at the end as usable variables?
  • JPeJPe Member
    DIYglenn said:

    This is the payload that you received,   (payload.length === 24) 
    you have to define an Address part, that is the pattern that Homey uses to recognize, so that part must always be the same, in this case, you can use the part from the second bit and leave away the last 2 bits, the counting starts with bit-0 so you need bit-1 to bit-22 (22 not included): address: this.bitArrayToString(payload.slice(1, 22)),  x000011111100010000000xx
    For 
    state: payload[1], //   I would take a bit that is always 1 so probably bit-6  state: payload[6], // since it's a pushbutton, there is no real "state", if it was a switch, you should take the bit that is changing with ON and OFF.
    Then there is the part: 
    data.address && data.address.length === 16 &&  that must fit your signal, so this must be 
    data &&
    data.address && data.address.length === 21 &&
    typeof data.state !== 'undefined'   // "state" we have fixed to 1, so i will never be 'undefined'  ( !==  means not ).
Sign In or Register to comment.