Skip to content

Commit 02755d6

Browse files
committed
First release
1 parent 827531b commit 02755d6

File tree

2 files changed

+89
-46
lines changed

2 files changed

+89
-46
lines changed

README.md

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
# sensus
2-
Sensus IR & RF Codes converter
3-
**[View online](https://pasthev.github.io/sensus/)**
1+
# sensus IR & RF codes converter / analyzer for Lirc, Pronto, Broadlink & raw codes
42

5-
### Sensus IR & RF codes converter / analyzer for Lirc, Pronto, Broadlink & raw codes
3+
**[View online](https://pasthev.github.io/sensus/)**
64

75
A project to provide an online IR/RF code converting interface and framework.
86
The tool doesn't do as much as dedicated software (i.e. IRscrutinizer), but has the
97
advantage of being instantly available online.
108
Interface is easy to update with additional panels if needed - feel free to fork and
119
add your own protocols.
1210

11+
Short "thank you", positive or negative feedback always appreciated: use this [anonymous contact form](https://docs.google.com/forms/d/e/1FAIpQLSckf2f04hYhTN3T6GvchbxhjhKcYHLMRDXnrRfqlM_eRW_NiA/viewform?usp=sf_link)
12+
13+
---
1314

1415
## What Sensus IR & RF does
1516

@@ -34,31 +35,40 @@ add your own protocols.
3435
* Allows to pre-set Repeat values
3536
* Allows to pre-set Signal type (IR / RF433 / RF315)
3637

37-
Note that Broadlink random functions generate One-Hot sequences, mostly used for RF signals,
38-
while other random functions generate Nec sequences, usualy designed for IR signals.
39-
This should fit most use, but you can rely on the Convert functions if you need to swap these
40-
defaults, i.e.:
41-
To get a random Broadlink IR (Nec) sequence, generate a random Raw, then convert to Broadlink.
42-
To get a random Pronto RF (One-Hot) sequence, generate a random Broadling, and convert to Pronto.
43-
4438
### IR/RF frames analysis
4539
* Frames decoding in detailled logged view
4640
* Identification of Nec5 and One-Hot encoded payloads
4741
* Identification of original Lirc command and possible manufacturer's code from raw frame
4842
* Cleanup and re-generation of learnt IR/RF packets
43+
44+
---
45+
46+
## Notes
47+
### Code conversion to and from:
48+
* Some values are slightly changed during conversion or frequency set. I.e. setting Header as "2512, 5520" in Commands panel, then converting to and back from Pronto results in Header becoming "2524, 5522"
49+
* this is intended, and due to the way values have to be stored in the various formats. In the example above, the converted "2524, 5522" header will remain stable no matter which format it is converted to.
50+
51+
### Frequency change
52+
* Changing frequency in Pronto and Decimal panels only changes frequency info packet and not actual payload values:
53+
* this is intended, since both changing frequency and converting timecodes in payload would lead to the exact same result as changing nothing - same spirit as 2x(14 days) = 4x(1 week). For this reason, the only place where changing frequency will actually lead to a payload conversion is the Raw panel.
54+
55+
### Random IR / RF codes generation:
56+
* Broadlink random functions generate One-Hot sequences, mostly used for RF signals, while other random functions generate Nec sequences, usualy designed for IR signals. This should fit most use, but you can rely on the Convert functions if you need to swap these defaults, i.e.:
57+
* To get a random Broadlink IR (Nec) sequence, generate a random Raw, then convert to Broadlink.
58+
* To get a random Pronto RF (One-Hot) sequence, generate a random Broadlink, and convert to Pronto.
59+
60+
### IR/RF frames analysis
61+
* The *Raw* Analysis panel acts both as a log window when needed, and as a raw analyzer through functions described below. Since this analysis is performed on the content of the Raw panel, all other formats must first be converted to Raw before running any of these analysis:
62+
* **Read raw**: Checks raw data for a binary sequence, and tries to decompose the signal. If succesful, result will be pushed to the *Command* panel.
63+
* *Header length* and *Trailer length* values define the number of beginning and ending values to force-ignore. These values are updated upon completion of the *Read Raw* function.
64+
* **Check**: A simple feature throwing some info about the content of the *Raw* panel, which can be useful when analyzing an unknown signal. I.e. copy a long binary string, and *Check* function will count bits, convert values to decimal and hex, invert bits, etc. Copy a series of values, and *Check* function will count these values, search for repeat strings, etc.
65+
* **Repeats**: A strange and sometimes useful feature that will identify and remove the last occurrence of the longest repeated string found in *Raw* panel.
66+
67+
---
4968

5069
## About the code
5170

52-
There are many other IR/RF standards that I just ignored here: so far I only added the ones
53-
I was facing, during my experiments with Home Assistant and Jeedom domotic solutions...
54-
But the html/css interface I'm providing makes it easy to add panels for other protocols,
55-
and the code should be documented enough for anyone to easily add components of their own,
56-
as well as new buttons to the Raw analysis interface when needed.
71+
*There are many other IR/RF standards that I just ignored here: so far I only added the ones I was facing, during my experiments with Home Assistant and Jeedom domotic solutions... But the html/css interface I'm providing makes it easy to add panels for other protocols, and the code should be documented enough for anyone to easily add components of their own, as well as new buttons to the Raw analysis interface when needed.*
5772

58-
Both the Js, css and html code can certainly be improved. Happy to learn, so, forks welcome.
59-
60-
## Notes
61-
* Changing frequency in Pronto and Decimal panels only changes frequency info packet and not actual payload values:
62-
* this is intended, since both changing frequency and converting timecodes in payload would lead to the exact same result as changing nothing - same spirit as 2x(14 days) = 4x(1 week). For this reason, the only place where changing frequency will actually lead to a payload conversion is the Raw panel.
63-
* Some values are slightly changed during conversion or frequency set. I.e. setting Header as "2512, 5520" ir Commands panel, then converting to and back from Pronto results in Header becoming "2524, 5522"
64-
* this is intended, and due to the way values have to be stored in the various formats. In the example above, the converted "2524, 5522" header will remain stable no matter which format it is converted to.
73+
*Both the Js, css and html code can certainly be improved. Happy to learn, so, forks welcome.*
74+
*

script.js

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ function stringType(str) { // _Tells
407407

408408
if (!str.replace(/ /g, '')) {return 'empty string'};
409409

410-
let cln = str.replace(/[L ;,.()\+\-]/g, ''); // test string after removing ' L;,()+-' chars
410+
let cln = str.replace(/[L ;,.()\+\-\r\n]/g, ''); // test string after removing ' L;,()+-' chars
411411

412412
if (/^[0-1]+$/.test(cln)) { // Case binary
413413
return { // Returns an object - Sample values:
@@ -418,7 +418,7 @@ function stringType(str) { // _Tells
418418
}
419419

420420

421-
if (/^\d+$/.test(cln)) { // Case hexadecimal (\d is exactly equivalent to [0-9] in js)
421+
if (/^\d+$/.test(cln)) { // Case decimal (\d is exactly equivalent to [0-9] in js)
422422
cln = str.replace(/[L ;()\+]/g, '')
423423
return { // Returns an object - Sample values:
424424
'type': 'decimal', // 'decimal'
@@ -1127,7 +1127,7 @@ function acmeCommands() { // Fills Commands data with test values
11271127
setField('cPtrailField', random.ptrail);
11281128
setField('cGapField', random.gap);
11291129
let freq = parseInt(getField('cFreqField')); // Frequency verification
1130-
if (!checkFreqInput(freq, true)) { // if Command Freq field is empty or user has typed a wrong value,
1130+
if (!checkFreqInput(freq, false)) { // if Command Freq field is empty or user has typed a wrong value,
11311131
setField('cFreqField', FREQ38); // defaults to 38 KHz
11321132
} //
11331133
}
@@ -1199,7 +1199,7 @@ function acmeBroadGen(sigType, repeats) { // _Generates random Broa
11991199
let freq = FREQ38; // arbitrary, as we don't really care here since Broadlink won't store freq value
12001200
let pronto = getProntoFromRaw(raw, freq);
12011201
let broadlinkHex = getBroadlink(pronto, sigType).join('');
1202-
if (checkRepeatsInput(repeats)) {
1202+
if (checkRepeatsInput(repeats, false)) {
12031203
broadlinkHex = setHexRepeats(broadlinkHex, repeats);
12041204
}
12051205

@@ -1229,7 +1229,7 @@ function ui_freq(button) { // Frequency buttons in Commands
12291229
setField('cFreqField', FREQ40);
12301230
}
12311231
}
1232-
function checkFreqInput(freq, warn) {
1232+
function checkFreqInput(freq, warn) { // Check frequency %freq, and throws a warning if invalid and %warn = true
12331233
if (freq > 63 && freq < 4145146) { return true };
12341234
if (warn) {message("Frequency must be between 63 Hz and 4145146 Hz")};
12351235
return false;
@@ -1455,7 +1455,7 @@ function ui_hexSetRepeats() { // ** Main- Change Broadlin
14551455
let hex = getField('broadlinkField');
14561456
let repeats = parseInt(getField('hexRepeats'));
14571457

1458-
if (checkRepeatsInput(repeats)) {
1458+
if (checkRepeatsInput(repeats, true)) {
14591459
setField('broadlinkField', setHexRepeats(hex,repeats));
14601460
}
14611461
setFocus('hexRepeats');
@@ -1468,7 +1468,7 @@ function ui_b64SetRepeats() { // ** Main- Change Broadlin
14681468
let b64 = getField('broadB64Field');
14691469
let repeats = parseInt(getField('b64Repeats'));
14701470

1471-
if (checkRepeatsInput(repeats)) {
1471+
if (checkRepeatsInput(repeats, true)) {
14721472
let newHex = setHexRepeats(base64ToHex(b64),repeats);
14731473
setField('broadB64Field', hexToBase64(newHex));
14741474
}
@@ -1489,9 +1489,9 @@ function setHexRepeats(hex,vrepeats) { // _Sets number of r
14891489
let repeats = vrepeats.toString(16).padStart(2, '0');
14901490
return lstring + repeats + rstring;
14911491
}
1492-
function checkRepeatsInput(repeats) { // _sanity check on repeats value, returns true if OK
1492+
function checkRepeatsInput(repeats, warn) { // _sanity check on repeats value, returns true if OK, else throws a warning if %warn = true
14931493
if (repeats >= 0 && repeats < 256) { return true };
1494-
message("Repeats value must be between 0 and 255");
1494+
if (warn) {message("Repeats value must be between 0 and 255")};
14951495
return false;
14961496
}
14971497

@@ -1559,9 +1559,15 @@ function convertCodes() { // ** Main- Converts all f
15591559
}
15601560
function ui_convertPronto() { // Convert from Pronto button
15611561
cleanOnClick();
1562-
convertPronto(getField('prontoField'));
1563-
refreshAll(true);
1564-
setFocus('prontoField');
1562+
let pronto = getField('prontoField');
1563+
let obj = stringType(pronto);
1564+
if (obj.type != 'invalid') { // Both 'binary', 'decimal', and 'hex' returned types can be hex, so, accept all but 'invalid' here
1565+
convertPronto(pronto);
1566+
refreshAll(true);
1567+
setFocus('prontoField');
1568+
} else {
1569+
message('Pronto string should contain only hexadecimal values, separated with spaces');
1570+
}
15651571
// return false;
15661572
}
15671573
function convertPronto(pronto) { // ** Main- Converts all fields from Pronto string value ***************
@@ -1575,10 +1581,16 @@ function convertPronto(pronto) { // ** Main- Converts all f
15751581
}
15761582
function ui_convertDecimal() { // Convert from decimal button
15771583
cleanOnClick();
1578-
convertDecimal(getField('decimalField'));
1579-
refreshAll(true);
1580-
setFocus('decimalField');
1581-
// return false;
1584+
let decimal = getField('decimalField');
1585+
let obj = stringType(decimal);
1586+
if (obj.type == 'decimal') { // 'binary' might also be accepted in theory, but decimal packet should include header, unlikely to be binary
1587+
convertDecimal(decimal);
1588+
refreshAll(true);
1589+
setFocus('decimalField');
1590+
} else {
1591+
message('Decimal string should contain only numbers, possibly with L markers and comma separators');
1592+
}
1593+
// return false;
15821594
}
15831595
function convertDecimal(decimal) { // ** Main- Converts all fields from decimal string value **************
15841596

@@ -1592,9 +1604,15 @@ function convertDecimal(decimal) { // ** Main- Converts all f
15921604
}
15931605
function ui_convertRaw() { // Convert from Raw button
15941606
cleanOnClick();
1595-
convertRaw(getField('rawField'));
1596-
setFocus('rawField');
1597-
refreshAll(true);
1607+
let raw = getField('rawField');
1608+
let obj = stringType(raw);
1609+
if (obj.type == 'decimal') { // 'binary' might also be accepted in theory, but decimal packet should include header, unlikely to be binary
1610+
convertRaw(raw);
1611+
setFocus('rawField');
1612+
refreshAll(true);
1613+
} else {
1614+
message('Raw string should contain only numbers, with comma separators');
1615+
}
15981616
// return false;
15991617
}
16001618
function convertRaw(raw) { // ** Main- Converts all fields from Raw string value *****************
@@ -1620,9 +1638,15 @@ function convertRaw(raw) { // ** Main- Converts all f
16201638
}
16211639
function ui_convertBroadlink() { // Convert from Broadlink Hex button
16221640
cleanOnClick();
1623-
convertBroadlink(getField('broadlinkField'));
1624-
refreshAll(true);
1625-
setFocus('broadlinkField');
1641+
let broadlink = getField('broadlinkField');
1642+
let obj = stringType(broadlink);
1643+
if (obj.type != 'invalid') { // Both 'binary', 'decimal', and 'hex' returned types can be hex, so, accept all but 'invalid' here
1644+
convertBroadlink(obj.cleaned); // Using returned obj.cleaned here rather than broadlink allows to remove spaces and other ,.; etc.
1645+
refreshAll(true);
1646+
setFocus('broadlinkField');
1647+
} else {
1648+
message('Broadlink string should contain only hexadecimal characters');
1649+
}
16261650
// return false;
16271651
}
16281652
function convertBroadlink(broadlinkHex) { // ** Main- Converts all fields from Broadlink string value ************
@@ -1647,7 +1671,16 @@ function convertBroadlink(broadlinkHex) { // ** Main- Converts all f
16471671
}
16481672
function ui_convertB64() { // Convert from Broadlink B64 button
16491673
cleanOnClick();
1650-
convertB64(getField('broadB64Field'));
1674+
let b64 = getField('broadB64Field');
1675+
try {
1676+
window.atob(b64.replace(/[ \r\n]+$/, ""));
1677+
} catch(e) {
1678+
if (e.code === 5) {
1679+
message('Base 64 format not recognized in Broadlink B64 field');
1680+
}
1681+
return;
1682+
}
1683+
convertB64(b64);
16511684
refreshAll(true);
16521685
setFocus('broadB64Field');
16531686
// return false;

0 commit comments

Comments
 (0)