Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

831 lines
24 KiB

Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Terminal: change command-line parser (#2247) Change the underlying command line handling: - switch to a custom parser, inspired by redis / sds - update terminalRegisterCommand signature, pass only bare minimum - clean-up `help` & `commands`. update settings `set`, `get` and `del` - allow our custom test suite to run command-line tests - clean-up Stream IO to allow us to print large things into debug stream (for example, `eeprom.dump`) - send parsing errors to the debug log As a proof of concept, introduce `TERMINAL_MQTT_SUPPORT` and `TERMINAL_WEB_API_SUPPORT` - MQTT subscribes to the `<root>/cmd/set` and sends response to the `<root>/cmd`. We can't output too much, as we don't have any large-send API. - Web API listens to the `/api/cmd?apikey=...&line=...` (or PUT, params inside the body). This one is intended as a possible replacement of the `API_SUPPORT`. Internals introduce a 'task' around the AsyncWebServerRequest object that will simulate what WiFiClient does and push data into it continuously, switching between CONT and SYS. Both are experimental. We only accept a single command and not every command is updated to use Print `ctx.output` object. We are also somewhat limited by the Print / Stream overall, perhaps I am overestimating the usefulness of Arduino compatibility to such an extent :) Web API handler can also sometimes show only part of the result, whenever the command tries to yield() by itself waiting for something. Perhaps we would need to create a custom request handler for that specific use-case.
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
Update rpnlib to 0.23.x (#2274) ## [0.23.0] 2020-07-26 ### Added - `p` operator to print the top of the stack via debug function - `&var` syntax to create variable reference in expression - `=` operator for variable assignment in expression - `exists` operator to check for variable existance (only for references) - `deref` operator to convert variable reference into a value (only for references) - Allow to use either float or double as floating type, parse numbers in expressions as specified type - Add boolean type, parse `true` and `false` in expressions - Add null type, parse `null` in expressions - Add string type, parse double-quoted `"string"` in expressions - Add integer and unsigned integer type, used in operators - Allow to configure underlying types from rpnlib\_config.h and -D... flags - Return `rpn_error` from operators, split error types into categories - Create a new stack by using `[` keyword. Move stack contents into the previous stack + size by using `]`. ### Changed - Stack structure no longer holds raw `float`, but internal `rpn_value` type - rpn\_... setter and getter methods use `rpn_value` type - Operator functions return `rpn_error` type, allowing to return both value and operator errors - Variables in expressions are no longer required to exist when using `&var` Expression will automatically create the variable, set it to `null` and push it's reference on the stack - It is possible to create 'reference' stack values - Improve precision of `e` and `pi` ### Fixed - Proper value for `e` constant - Allow to use multiple contexts simultaniously, replace `rpn_error` and `rpn_debug_callback` with the current `rpn_context` members `error` and `debug_callback` respectively
4 years ago
  1. /*
  2. RPN RULES MODULE
  3. Use RPNLib library (https://github.com/xoseperez/rpnlib)
  4. Copyright (C) 2019 by Xose Pérez <xose dot perez at gmail dot com>
  5. */
  6. #include "rpnrules.h"
  7. #if RPN_RULES_SUPPORT
  8. #include "broker.h"
  9. #include "mqtt.h"
  10. #include "ntp.h"
  11. #include "relay.h"
  12. #include "rpc.h"
  13. #include "sensor.h"
  14. #include "rfbridge.h"
  15. #include "terminal.h"
  16. #include "ws.h"
  17. #include <list>
  18. #include <vector>
  19. // -----------------------------------------------------------------------------
  20. // Custom commands
  21. // -----------------------------------------------------------------------------
  22. rpn_context _rpn_ctxt;
  23. bool _rpn_run = false;
  24. unsigned long _rpn_delay = RPN_DELAY;
  25. unsigned long _rpn_last = 0;
  26. struct RpnRunner {
  27. enum class Policy {
  28. OneShot,
  29. Periodic
  30. };
  31. RpnRunner(Policy policy_, uint32_t period_) :
  32. policy(policy_),
  33. period(period_),
  34. last(millis())
  35. {}
  36. Policy policy { Policy::Periodic };
  37. uint32_t period { 0ul };
  38. uint32_t last { 0ul };
  39. bool expired { false };
  40. };
  41. std::vector<RpnRunner> _rpn_runners;
  42. rpn_operator_error _rpnRunnerHandler(rpn_context & ctxt, RpnRunner::Policy policy, uint32_t time) {
  43. for (auto& runner : _rpn_runners) {
  44. if ((policy == runner.policy) && (time == runner.period)) {
  45. return runner.expired
  46. ? rpn_operator_error::Ok
  47. : rpn_operator_error::CannotContinue;
  48. }
  49. }
  50. _rpn_runners.emplace_back(policy, time);
  51. return rpn_operator_error::CannotContinue;
  52. }
  53. // -----------------------------------------------------------------------------
  54. bool _rpnWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
  55. return (strncmp(key, "rpn", 3) == 0);
  56. }
  57. void _rpnWebSocketOnConnected(JsonObject& root) {
  58. root["rpnSticky"] = getSetting("rpnSticky", 1 == RPN_STICKY);
  59. root["rpnDelay"] = getSetting("rpnDelay", RPN_DELAY);
  60. JsonArray& rules = root.createNestedArray("rpnRules");
  61. unsigned char i = 0;
  62. String rule = getSetting({"rpnRule", i});
  63. while (rule.length()) {
  64. rules.add(rule);
  65. rule = getSetting({"rpnRule", ++i});
  66. }
  67. #if MQTT_SUPPORT
  68. i=0;
  69. JsonArray& topics = root.createNestedArray("rpnTopics");
  70. JsonArray& names = root.createNestedArray("rpnNames");
  71. String rpn_topic = getSetting({"rpnTopic", i});
  72. while (rpn_topic.length() > 0) {
  73. String rpn_name = getSetting({"rpnName", i});
  74. topics.add(rpn_topic);
  75. names.add(rpn_name);
  76. rpn_topic = getSetting({"rpnTopic", ++i});
  77. }
  78. #endif
  79. }
  80. #if MQTT_SUPPORT
  81. void _rpnMQTTSubscribe() {
  82. unsigned char i = 0;
  83. String rpn_topic = getSetting({"rpnTopic", i});
  84. while (rpn_topic.length()) {
  85. mqttSubscribeRaw(rpn_topic.c_str());
  86. rpn_topic = getSetting({"rpnTopic", ++i});
  87. }
  88. }
  89. void _rpnMQTTCallback(unsigned int type, const char * topic, const char * payload) {
  90. if (type == MQTT_CONNECT_EVENT) {
  91. _rpnMQTTSubscribe();
  92. }
  93. if (type == MQTT_MESSAGE_EVENT) {
  94. unsigned char i = 0;
  95. String rpn_topic = getSetting({"rpnTopic", i});
  96. while (rpn_topic.length()) {
  97. if (rpn_topic.equals(topic)) {
  98. String rpn_name = getSetting({"rpnName", i});
  99. if (rpn_name.length()) {
  100. rpn_value value { atof(payload) };
  101. rpn_variable_set(_rpn_ctxt, rpn_name, value);
  102. _rpn_run = true;
  103. break;
  104. }
  105. }
  106. rpn_topic = getSetting({"rpnTopic", ++i});
  107. }
  108. }
  109. }
  110. #endif // MQTT_SUPPORT
  111. void _rpnConfigure() {
  112. #if MQTT_SUPPORT
  113. if (mqttConnected()) _rpnMQTTSubscribe();
  114. #endif
  115. _rpn_delay = getSetting("rpnDelay", RPN_DELAY);
  116. }
  117. void _rpnBrokerCallback(const String& topic, unsigned char id, double value, const char*) {
  118. char name[32] = {0};
  119. snprintf(name, sizeof(name), "%s%u", topic.c_str(), id);
  120. if (topic == MQTT_TOPIC_RELAY) {
  121. rpn_variable_set(_rpn_ctxt, name, rpn_value(static_cast<bool>(value)));
  122. } else {
  123. rpn_variable_set(_rpn_ctxt, name, rpn_value(value));
  124. }
  125. _rpn_run = true;
  126. }
  127. void _rpnBrokerStatus(const String& topic, unsigned char id, unsigned int value) {
  128. _rpnBrokerCallback(topic, id, double(value), nullptr);
  129. }
  130. #if NTP_SUPPORT
  131. rpn_error _rpnNtpNow(rpn_context & ctxt) {
  132. if (!ntpSynced()) return rpn_operator_error::CannotContinue;
  133. rpn_value ts { static_cast<rpn_int>(now()) };
  134. rpn_stack_push(ctxt, ts);
  135. return 0;
  136. }
  137. rpn_error _rpnNtpFunc(rpn_context & ctxt, rpn_int (*func)(time_t)) {
  138. rpn_value value;
  139. rpn_stack_pop(ctxt, value);
  140. value = rpn_value(func(value.toInt()));
  141. rpn_stack_push(ctxt, value);
  142. return 0;
  143. }
  144. #endif // NTP_SUPPORT
  145. String _rpnValueToString(const rpn_value& value) {
  146. String out;
  147. if (value.isString()) {
  148. out = value.toString();
  149. } else if (value.isFloat()) {
  150. out = String(value.toFloat(), 10);
  151. } else if (value.isInt()) {
  152. out = String(value.toInt(), 10);
  153. } else if (value.isUint()) {
  154. out = String(value.toUint(), 10);
  155. } else if (value.isBoolean()) {
  156. out = String(value.toBoolean() ? "true" : "false");
  157. } else if (value.isNull()) {
  158. out = F("(null)");
  159. }
  160. return out;
  161. }
  162. char _rpnStackTypeTag(rpn_stack_value::Type type) {
  163. switch (type) {
  164. case rpn_stack_value::Type::None:
  165. return 'N';
  166. case rpn_stack_value::Type::Variable:
  167. return '$';
  168. case rpn_stack_value::Type::Array:
  169. return 'A';
  170. case rpn_stack_value::Type::Value:
  171. default:
  172. return ' ';
  173. }
  174. }
  175. #if RELAY_SUPPORT
  176. rpn_error _rpnRelayStatus(rpn_context & ctxt, bool force) {
  177. rpn_value id;
  178. rpn_value status;
  179. rpn_stack_pop(ctxt, id);
  180. rpn_stack_pop(ctxt, status);
  181. rpn_uint value = status.toUint();
  182. if (value == 2) {
  183. relayToggle(id.toUint());
  184. } else if (relayStatusTarget(id.toUint()) != (value == 1)) {
  185. relayStatus(id.toUint(), value == 1);
  186. }
  187. return 0;
  188. }
  189. #endif // RELAY_SUPPORT
  190. #if RFB_SUPPORT
  191. struct rpn_rfbridge_code {
  192. unsigned char protocol;
  193. String raw;
  194. size_t count;
  195. decltype(millis()) last;
  196. };
  197. // TODO: in theory, we could do with forward_list. however, this would require a more complicated removal process,
  198. // as we would no longer know the previous element and would need to track 2 elements at a time
  199. static std::list<rpn_rfbridge_code> _rfb_codes;
  200. static uint32_t _rfb_code_repeat_window;
  201. static uint32_t _rfb_code_stale_delay;
  202. static uint32_t _rfb_code_match_window;
  203. struct rpn_rfbridge_match {
  204. unsigned char protocol;
  205. String raw;
  206. };
  207. rpn_error _rpnRfbSequence(rpn_context& ctxt) {
  208. auto raw_second = rpn_stack_pop(ctxt);
  209. auto proto_second = rpn_stack_pop(ctxt);
  210. auto raw_first = rpn_stack_pop(ctxt);
  211. auto proto_first = rpn_stack_pop(ctxt);
  212. // find 2 codes in the same order and save pointers
  213. rpn_rfbridge_match match[2] {
  214. {static_cast<unsigned char>(proto_first.toUint()), raw_first.toString()},
  215. {static_cast<unsigned char>(proto_second.toUint()), raw_second.toString()}
  216. };
  217. rpn_rfbridge_code* refs[2] {nullptr, nullptr};
  218. for (auto& recent : _rfb_codes) {
  219. if ((refs[0] != nullptr) && (refs[1] != nullptr)) {
  220. break;
  221. }
  222. for (int index = 0; index < 2; ++index) {
  223. if ((refs[index] == nullptr)
  224. && (match[index].protocol == recent.protocol)
  225. && (match[index].raw == recent.raw)) {
  226. refs[index] = &recent;
  227. }
  228. }
  229. }
  230. if ((refs[0] == nullptr) || (refs[1] == nullptr)) {
  231. return rpn_operator_error::CannotContinue;
  232. }
  233. // purge codes to avoid matching again on the next rules run
  234. if ((millis() - refs[0]->last) > (millis() - refs[1]->last)) {
  235. _rfb_codes.remove_if([&refs](rpn_rfbridge_code& code) {
  236. return (refs[0] == &code) || (refs[1] == &code);
  237. });
  238. return rpn_operator_error::Ok;
  239. }
  240. return rpn_operator_error::CannotContinue;
  241. }
  242. decltype(_rfb_codes)::iterator _rpnRfbFindCode(unsigned char protocol, const String& match) {
  243. return std::find_if(_rfb_codes.begin(), _rfb_codes.end(), [protocol, &match](const rpn_rfbridge_code& code) {
  244. return (code.protocol == protocol) && (code.raw == match);
  245. });
  246. }
  247. rpn_error _rpnRfbPop(rpn_context& ctxt) {
  248. auto code = rpn_stack_pop(ctxt);
  249. auto proto = rpn_stack_pop(ctxt);
  250. auto result = _rpnRfbFindCode(proto.toUint(), code.toString());
  251. if (result == _rfb_codes.end()) {
  252. return rpn_operator_error::CannotContinue;
  253. }
  254. _rfb_codes.erase(result);
  255. return rpn_operator_error::Ok;
  256. }
  257. rpn_error _rpnRfbInfo(rpn_context& ctxt) {
  258. auto code = rpn_stack_pop(ctxt);
  259. auto proto = rpn_stack_pop(ctxt);
  260. auto result = _rpnRfbFindCode(proto.toUint(), code.toString());
  261. if (result == _rfb_codes.end()) {
  262. return rpn_operator_error::CannotContinue;
  263. }
  264. rpn_stack_push(ctxt, rpn_value(
  265. static_cast<rpn_uint>((*result).count)));
  266. rpn_stack_push(ctxt, rpn_value(
  267. static_cast<rpn_uint>((*result).last)));
  268. return rpn_operator_error::Ok;
  269. }
  270. rpn_error _rpnRfbWaitMatch(rpn_context& ctxt) {
  271. auto code = rpn_stack_pop(ctxt);
  272. auto proto = rpn_stack_pop(ctxt);
  273. auto count = rpn_stack_pop(ctxt);
  274. auto time = rpn_stack_pop(ctxt);
  275. auto result = _rpnRfbFindCode(proto.toUint(), code.toString());
  276. if (result == _rfb_codes.end()) {
  277. return rpn_operator_error::CannotContinue;
  278. }
  279. if ((*result).count < count.toUint()) {
  280. return rpn_operator_error::CannotContinue;
  281. }
  282. // purge code to avoid matching again on the next rules run
  283. if (rpn_operator_error::Ok == _rpnRunnerHandler(ctxt, RpnRunner::Policy::OneShot, time.toUint())) {
  284. _rfb_codes.erase(result);
  285. return rpn_operator_error::Ok;
  286. }
  287. return rpn_operator_error::CannotContinue;
  288. }
  289. rpn_error _rpnRfbMatcher(rpn_context& ctxt) {
  290. auto code = rpn_stack_pop(ctxt);
  291. auto proto = rpn_stack_pop(ctxt);
  292. auto count = rpn_stack_pop(ctxt);
  293. auto result = _rpnRfbFindCode(proto.toUint(), code.toString());
  294. if (result == _rfb_codes.end()) {
  295. return rpn_operator_error::CannotContinue;
  296. }
  297. // only process recent codes, ignore when rule is processing outside of this small window
  298. if (millis() - (*result).last >= _rfb_code_match_window) {
  299. return rpn_operator_error::CannotContinue;
  300. }
  301. // purge code to avoid matching again on the next rules run
  302. if ((*result).count == count.toUint()) {
  303. _rfb_codes.erase(result);
  304. return rpn_operator_error::Ok;
  305. }
  306. return rpn_operator_error::CannotContinue;
  307. }
  308. void _rpnBrokerRfbridgeCallback(unsigned char protocol, const char* raw_code) {
  309. // remove really old codes that we have not seen in a while to avoid memory exhaustion
  310. auto ts = millis();
  311. auto old = std::remove_if(_rfb_codes.begin(), _rfb_codes.end(), [ts](rpn_rfbridge_code& code) {
  312. return (ts - code.last) >= _rfb_code_stale_delay;
  313. });
  314. if (old != _rfb_codes.end()) {
  315. _rfb_codes.erase(old, _rfb_codes.end());
  316. }
  317. auto result = _rpnRfbFindCode(protocol, raw_code);
  318. if (result != _rfb_codes.end()) {
  319. // we also need to reset the counter at a certain point to allow next batch of repeats to go through
  320. if (millis() - (*result).last >= _rfb_code_repeat_window) {
  321. (*result).count = 0;
  322. }
  323. (*result).last = millis();
  324. (*result).count += 1u;
  325. } else {
  326. _rfb_codes.push_back({protocol, raw_code, 1u, millis()});
  327. }
  328. _rpn_run = true;
  329. }
  330. void _rpnRfbSetup() {
  331. // - Repeat window is an arbitrary time, just about 3-4 more times it takes for
  332. // a code to be sent again when holding a generic remote button
  333. // Code counter is reset to 0 when outside of the window.
  334. // - Stale delay allows broker callback to remove really old codes.
  335. // (TODO: can this happen in loop() cb instead?)
  336. _rfb_code_repeat_window = getSetting("rfbRepeatWindow", 2000ul);
  337. _rfb_code_match_window = getSetting("rfbMatchWindow", 2000ul);
  338. _rfb_code_stale_delay = getSetting("rfbStaleDelay", 10000ul);
  339. #if TERMINAL_SUPPORT
  340. terminalRegisterCommand(F("RFB.CODES"), [](const terminal::CommandContext& ctx) {
  341. for (auto& code : _rfb_codes) {
  342. char buffer[128] = {0};
  343. snprintf_P(buffer, sizeof(buffer),
  344. PSTR("\"%s\" proto=%u count=%u last=%u"),
  345. code.protocol,
  346. code.raw.c_str(),
  347. code.count,
  348. code.last
  349. );
  350. ctx.output.println(buffer);
  351. }
  352. });
  353. #endif
  354. // Main bulk of the processing goes on in here
  355. RfbridgeBroker::Register(_rpnBrokerRfbridgeCallback);
  356. }
  357. #endif // RFB_SUPPORT
  358. void _rpnShowStack(Print& print) {
  359. print.println(F("Stack:"));
  360. auto index = rpn_stack_size(_rpn_ctxt);
  361. if (!index) {
  362. print.println(F(" (empty)"));
  363. return;
  364. }
  365. rpn_stack_foreach(_rpn_ctxt, [&index, &print](rpn_stack_value::Type type, const rpn_value& value) {
  366. print.printf("%c %02u: %s\n",
  367. _rpnStackTypeTag(type), index--,
  368. _rpnValueToString(value).c_str()
  369. );
  370. });
  371. }
  372. void _rpnInit() {
  373. // Init context
  374. rpn_init(_rpn_ctxt);
  375. // Time functions need NTP support
  376. // TODO: since 1.15.0, timelib+ntpclientlib are no longer used with latest Cores
  377. // `now` is always in UTC, `utc_...` functions to be used instead to convert time
  378. #if NTP_SUPPORT && !NTP_LEGACY_SUPPORT
  379. rpn_operator_set(_rpn_ctxt, "utc", 0, _rpnNtpNow);
  380. rpn_operator_set(_rpn_ctxt, "now", 0, _rpnNtpNow);
  381. rpn_operator_set(_rpn_ctxt, "utc_month", 1, [](rpn_context & ctxt) {
  382. return _rpnNtpFunc(ctxt, utc_month);
  383. });
  384. rpn_operator_set(_rpn_ctxt, "month", 1, [](rpn_context & ctxt) {
  385. return _rpnNtpFunc(ctxt, month);
  386. });
  387. rpn_operator_set(_rpn_ctxt, "utc_day", 1, [](rpn_context & ctxt) {
  388. return _rpnNtpFunc(ctxt, utc_day);
  389. });
  390. rpn_operator_set(_rpn_ctxt, "day", 1, [](rpn_context & ctxt) {
  391. return _rpnNtpFunc(ctxt, day);
  392. });
  393. rpn_operator_set(_rpn_ctxt, "utc_dow", 1, [](rpn_context & ctxt) {
  394. return _rpnNtpFunc(ctxt, utc_weekday);
  395. });
  396. rpn_operator_set(_rpn_ctxt, "dow", 1, [](rpn_context & ctxt) {
  397. return _rpnNtpFunc(ctxt, weekday);
  398. });
  399. rpn_operator_set(_rpn_ctxt, "utc_hour", 1, [](rpn_context & ctxt) {
  400. return _rpnNtpFunc(ctxt, utc_hour);
  401. });
  402. rpn_operator_set(_rpn_ctxt, "hour", 1, [](rpn_context & ctxt) {
  403. return _rpnNtpFunc(ctxt, hour);
  404. });
  405. rpn_operator_set(_rpn_ctxt, "utc_minute", 1, [](rpn_context & ctxt) {
  406. return _rpnNtpFunc(ctxt, utc_minute);
  407. });
  408. rpn_operator_set(_rpn_ctxt, "minute", 1, [](rpn_context & ctxt) {
  409. return _rpnNtpFunc(ctxt, minute);
  410. });
  411. #endif
  412. // TODO: 1.14.0 weekday(...) conversion seemed to have 0..6 range with Monday as 0
  413. // using classic Sunday as first, but instead of 0 it is 1
  414. // Implementation above also uses 1 for Sunday, staying compatible with TimeLib
  415. #if NTP_SUPPORT && NTP_LEGACY_SUPPORT
  416. rpn_operator_set(_rpn_ctxt, "utc", 0, [](rpn_context & ctxt) -> rpn_error {
  417. if (!ntpSynced()) return rpn_operator_error::CannotContinue;
  418. rpn_value ts { static_cast<rpn_int>(ntpLocal2UTC(now())) };
  419. rpn_stack_push(ctxt, ts);
  420. return 0;
  421. });
  422. rpn_operator_set(_rpn_ctxt, "now", 0, _rpnNtpNow);
  423. rpn_operator_set(_rpn_ctxt, "month", 1, [](rpn_context & ctxt) {
  424. return _rpnNtpFunc(ctxt, month);
  425. });
  426. rpn_operator_set(_rpn_ctxt, "day", 1, [](rpn_context & ctxt) {
  427. return _rpnNtpFunc(ctxt, day);
  428. });
  429. rpn_operator_set(_rpn_ctxt, "dow", 1, [](rpn_context & ctxt) {
  430. return _rpnNtpFunc(ctxt, weekday);
  431. });
  432. rpn_operator_set(_rpn_ctxt, "hour", 1, [](rpn_context & ctxt) {
  433. return _rpnNtpFunc(ctxt, hour);
  434. });
  435. rpn_operator_set(_rpn_ctxt, "minute", 1, [](rpn_context & ctxt) {
  436. return _rpnNtpFunc(ctxt, minute);
  437. });
  438. #endif
  439. // Accept relay number and numeric API status value (0, 1 and 2)
  440. #if RELAY_SUPPORT
  441. // apply status and reset timers when called
  442. rpn_operator_set(_rpn_ctxt, "relay_reset", 2, [](rpn_context & ctxt) {
  443. return _rpnRelayStatus(ctxt, true);
  444. });
  445. // only update status when target status differs, keep running timers
  446. rpn_operator_set(_rpn_ctxt, "relay", 2, [](rpn_context & ctxt) {
  447. return _rpnRelayStatus(ctxt, false);
  448. });
  449. #endif // RELAY_SUPPORT == 1
  450. // Channel operators
  451. #if RELAY_PROVIDER == RELAY_PROVIDER_LIGHT
  452. rpn_operator_set(_rpn_ctxt, "update", 0, [](rpn_context & ctxt) -> rpn_error {
  453. lightUpdate(true, true);
  454. return 0;
  455. });
  456. rpn_operator_set(_rpn_ctxt, "black", 0, [](rpn_context & ctxt) -> rpn_error {
  457. lightColor((unsigned long) 0);
  458. return 0;
  459. });
  460. rpn_operator_set(_rpn_ctxt, "channel", 2, [](rpn_context & ctxt) -> rpn_error {
  461. rpn_value value;
  462. rpn_value id;
  463. rpn_stack_pop(ctxt, id);
  464. rpn_stack_pop(ctxt, value);
  465. lightChannel(id.toUint(), id.toInt());
  466. return 0;
  467. });
  468. #endif
  469. #if RFB_SUPPORT
  470. rpn_operator_set(_rpn_ctxt, "rfb_pop", 2, _rpnRfbPop);
  471. rpn_operator_set(_rpn_ctxt, "rfb_info", 2, _rpnRfbInfo);
  472. rpn_operator_set(_rpn_ctxt, "rfb_sequence", 4, _rpnRfbSequence);
  473. rpn_operator_set(_rpn_ctxt, "rfb_match", 3, _rpnRfbMatcher);
  474. rpn_operator_set(_rpn_ctxt, "rfb_match_wait", 4, _rpnRfbWaitMatch);
  475. #endif
  476. #if MQTT_SUPPORT
  477. rpn_operator_set(_rpn_ctxt, "mqtt_send", 2, [](rpn_context & ctxt) -> rpn_error {
  478. rpn_value message;
  479. rpn_stack_pop(ctxt, message);
  480. rpn_value topic;
  481. rpn_stack_pop(ctxt, topic);
  482. return mqttSendRaw(topic.toString().c_str(), message.toString().c_str())
  483. ? rpn_operator_error::Ok
  484. : rpn_operator_error::CannotContinue;
  485. });
  486. #endif
  487. // Some debugging. Dump stack contents
  488. #if TERMINAL_SUPPORT
  489. rpn_operator_set(_rpn_ctxt, "showstack", 0, [](rpn_context & ctxt) -> rpn_error {
  490. _rpnShowStack(terminalDefaultStream());
  491. return 0;
  492. });
  493. #endif
  494. // And, simple string logging
  495. #if DEBUG_SUPPORT
  496. rpn_operator_set(_rpn_ctxt, "dbgmsg", 1, [](rpn_context & ctxt) -> rpn_error {
  497. rpn_value message;
  498. rpn_stack_pop(ctxt, message);
  499. DEBUG_MSG_P(PSTR("[RPN] %s\n"), message.toString().c_str());
  500. return 0;
  501. });
  502. #endif
  503. rpn_operator_set(_rpn_ctxt, "millis", 0, [](rpn_context & ctxt) -> rpn_error {
  504. rpn_stack_push(ctxt, rpn_value(static_cast<uint32_t>(millis())));
  505. return 0;
  506. });
  507. rpn_operator_set(_rpn_ctxt, "oneshot_ms", 1, [](rpn_context & ctxt) -> rpn_error {
  508. auto every = rpn_stack_pop(ctxt);
  509. return _rpnRunnerHandler(ctxt, RpnRunner::Policy::OneShot, every.toUint());
  510. });
  511. rpn_operator_set(_rpn_ctxt, "every_ms", 1, [](rpn_context & ctxt) -> rpn_error {
  512. auto every = rpn_stack_pop(ctxt);
  513. return _rpnRunnerHandler(ctxt, RpnRunner::Policy::Periodic, every.toUint());
  514. });
  515. }
  516. #if TERMINAL_SUPPORT
  517. void _rpnInitCommands() {
  518. terminalRegisterCommand(F("RPN.RUNNERS"), [](const terminal::CommandContext& ctx) {
  519. if (!_rpn_runners.size()) {
  520. terminalError(ctx, F("No active runners"));
  521. return;
  522. }
  523. for (auto& runner : _rpn_runners) {
  524. char buffer[128] = {0};
  525. snprintf_P(buffer, sizeof(buffer), PSTR("%p %s %u ms, last %u ms"),
  526. &runner, (RpnRunner::Policy::Periodic == runner.policy) ? "every" : "one-shot",
  527. runner.period, runner.last
  528. );
  529. ctx.output.println(buffer);
  530. }
  531. terminalOK(ctx);
  532. });
  533. terminalRegisterCommand(F("RPN.VARS"), [](const terminal::CommandContext& ctx) {
  534. rpn_variables_foreach(_rpn_ctxt, [&ctx](const String& name, const rpn_value& value) {
  535. char buffer[256] = {0};
  536. snprintf_P(buffer, sizeof(buffer), PSTR(" %s: %s"), name.c_str(), _rpnValueToString(value).c_str());
  537. ctx.output.println(buffer);
  538. });
  539. terminalOK(ctx);
  540. });
  541. terminalRegisterCommand(F("RPN.OPS"), [](const terminal::CommandContext& ctx) {
  542. rpn_operators_foreach(_rpn_ctxt, [&ctx](const String& name, size_t argc, rpn_operator::callback_type) {
  543. char buffer[128] = {0};
  544. snprintf_P(buffer, sizeof(buffer), PSTR(" %s (%d)"), name.c_str(), argc);
  545. ctx.output.println(buffer);
  546. });
  547. terminalOK(ctx);
  548. });
  549. terminalRegisterCommand(F("RPN.TEST"), [](const terminal::CommandContext& ctx) {
  550. if (ctx.argc != 2) {
  551. terminalError(F("Wrong arguments"));
  552. return;
  553. }
  554. ctx.output.print(F("Running RPN expression: "));
  555. ctx.output.println(ctx.argv[1].c_str());
  556. if (!rpn_process(_rpn_ctxt, ctx.argv[1].c_str())) {
  557. rpn_stack_clear(_rpn_ctxt);
  558. char buffer[64] = {0};
  559. snprintf_P(buffer, sizeof(buffer), PSTR("position=%u category=%d code=%d"),
  560. _rpn_ctxt.error.position, static_cast<int>(_rpn_ctxt.error.category), _rpn_ctxt.error.code);
  561. terminalError(ctx, buffer);
  562. return;
  563. }
  564. _rpnShowStack(ctx.output);
  565. rpn_stack_clear(_rpn_ctxt);
  566. terminalOK(ctx);
  567. });
  568. }
  569. #endif
  570. // enables us to use rules without any events firing
  571. // notice: requires rpnRun to trigger at least once so that we can install runners
  572. void _rpnRunnersCheck() {
  573. auto ts = millis();
  574. for (auto& runner : _rpn_runners) {
  575. if (ts - runner.last >= runner.period) {
  576. runner.expired = true;
  577. runner.last = ts;
  578. _rpn_run = true;
  579. }
  580. }
  581. }
  582. void _rpnRunnersReset() {
  583. auto old = std::remove_if(_rpn_runners.begin(), _rpn_runners.end(), [](RpnRunner& runner) {
  584. return (RpnRunner::Policy::OneShot == runner.policy) && runner.expired;
  585. });
  586. if (old != _rpn_runners.end()) {
  587. _rpn_runners.erase(old, _rpn_runners.end());
  588. }
  589. for (auto& runner : _rpn_runners) {
  590. runner.expired = false;
  591. }
  592. }
  593. void _rpnRun() {
  594. if (!_rpn_run) {
  595. return;
  596. }
  597. if (millis() - _rpn_last <= _rpn_delay) {
  598. return;
  599. }
  600. _rpn_last = millis();
  601. _rpn_run = false;
  602. String rule;
  603. unsigned char i = 0;
  604. while ((rule = getSetting({"rpnRule", i++})).length()) {
  605. rpn_process(_rpn_ctxt, rule.c_str());
  606. rpn_stack_clear(_rpn_ctxt);
  607. }
  608. if (!getSetting("rpnSticky", 1 == RPN_STICKY)) {
  609. rpn_variables_clear(_rpn_ctxt);
  610. }
  611. }
  612. void _rpnLoop() {
  613. _rpnRunnersCheck();
  614. _rpnRun();
  615. _rpnRunnersReset();
  616. }
  617. void rpnSetup() {
  618. // Init context
  619. _rpnInit();
  620. // Load & cache settings
  621. _rpnConfigure();
  622. // Terminal commands
  623. #if TERMINAL_SUPPORT
  624. _rpnInitCommands();
  625. #endif
  626. // Websockets
  627. #if WEB_SUPPORT
  628. wsRegister()
  629. .onVisible([](JsonObject& root) { root["rpnVisible"] = 1; })
  630. .onConnected(_rpnWebSocketOnConnected)
  631. .onKeyCheck(_rpnWebSocketOnKeyCheck);
  632. #endif
  633. // MQTT
  634. #if MQTT_SUPPORT
  635. mqttRegister(_rpnMQTTCallback);
  636. #endif
  637. #if NTP_SUPPORT
  638. NtpBroker::Register([](const NtpTick tick, time_t timestamp, const String& datetime) {
  639. static const String tick_every_hour(F("tick1h"));
  640. static const String tick_every_minute(F("tick1m"));
  641. const char* ptr =
  642. (tick == NtpTick::EveryMinute) ? tick_every_minute.c_str() :
  643. (tick == NtpTick::EveryHour) ? tick_every_hour.c_str() : nullptr;
  644. if (ptr != nullptr) {
  645. rpn_value value { static_cast<rpn_int>(timestamp) };
  646. rpn_variable_set(_rpn_ctxt, ptr, value);
  647. _rpn_run = true;
  648. }
  649. });
  650. #endif
  651. StatusBroker::Register(_rpnBrokerStatus);
  652. #if RFB_SUPPORT
  653. _rpnRfbSetup();
  654. #endif
  655. #if SENSOR_SUPPORT
  656. SensorReadBroker::Register(_rpnBrokerCallback);
  657. #endif
  658. espurnaRegisterReload(_rpnConfigure);
  659. espurnaRegisterLoop(_rpnLoop);
  660. _rpn_last = millis();
  661. _rpn_run = true;
  662. }
  663. #endif // RPN_RULES_SUPPORT