Skip to content

Commit

Permalink
Merge pull request #44 from jeedom/beta
Browse files Browse the repository at this point in the history
stable
  • Loading branch information
zoic21 authored Sep 9, 2024
2 parents 11468d4 + f4eab54 commit fe69694
Show file tree
Hide file tree
Showing 37 changed files with 1,089 additions and 119 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/work.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
on:
# Workflows check plugin Jeedom
push:
branches:
- beta
pull_request:
branches:
- beta
- master

name : 'Full Workflows Plugin Jeedom'

jobs:
plugin:
uses: jeedom/workflows/.github/workflows/plugin.yml@main
31 changes: 31 additions & 0 deletions core/ajax/mqtt2.ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@
ajax::success();
}

if (init('action') == 'sendToLocalMqtt') {
$configuration = json_decode(init('configuration'),true);
mqtt2::syncTopicToLocalMqtt(
$configuration['topic'].'-'.$configuration['id'],
$configuration['topic'],
$configuration['username'],
$configuration['password'],
$configuration['ip'],
$configuration['port']
);
if (!in_array($configuration['topic'].'-'.$configuration['id'],explode(',',config::byKey('jeedom::link', 'mqtt2')))) {
config::save('jeedom::link',trim(config::byKey('jeedom::link', 'mqtt2').','.$configuration['topic'].'-'.$configuration['id'],','),'mqtt2');
return;
}
ajax::success();
}

if (init('action') == 'eqLogicTransmitConfiguration') {
$eqLogics = json_decode(init('eqLogics'),true);
foreach ($eqLogics as $_eqLogic) {
Expand All @@ -43,6 +60,20 @@
}
ajax::success();
}

if (init('action') == 'sendToJeedomCloud') {
mqtt2::syncTopicToJeedomCloud(config::byKey('root_topic', 'mqtt2'),config::byKey('root_topic', 'mqtt2').'-'.substr(jeedom::getHardwareKey(),0,10));
ajax::success();
}

if (init('action') == 'receivedFromJeedomCloud') {
mqtt2::syncTopicToJeedomCloud(init('local_topic'),init('remote_topic'));
if (!in_array(init('local_topic'),explode(',',config::byKey('jeedom::link', 'mqtt2')))) {
config::save('jeedom::link',trim(config::byKey('jeedom::link', 'mqtt2').','.init('local_topic'),','),'mqtt2');
return;
}
ajax::success();
}


if (init('action') == 'installMosquitto') {
Expand Down
119 changes: 111 additions & 8 deletions core/class/mqtt2.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,88 @@

class mqtt2 extends eqLogic {

public static function createListenner(){
$listeners = listener::searchClassFunctionOption('mqtt2', 'handleEvent');
if(count($listeners) > 1){
foreach($listeners as $listener){
$listener->remove();
}
}
$listener = listener::byClassAndFunction('mqtt2', 'handleEvent');
if (!is_object($listener)) {
$listener = new listener();
}
$listener->setClass('mqtt2');
$listener->setFunction('handleEvent');
$listener->emptyEvent();
$listener->addEvent('*');
$listener->setOption(array('background' => false));
$listener->save();
}

public static function syncTopicToJeedomCloud($_local_topic = '',$_remote_topic = ''){
if($_local_topic == '' || $_remote_topic == ''){
throw new Exception(__('Le local topic et le remonte ne peuvent etre vide',__FILE__));
}
$_local_topic = trim($_local_topic);
$_remote_topic = trim($_remote_topic);
$local_authentifications = explode(':', explode("\n", config::byKey('mqtt::password', __CLASS__))[0]);
$conf = "# Begin autogenerate for ".$_local_topic." <-> cloud-".$_remote_topic."\n";
$conf .= "connection #cloud_username#-jeedom-".config::genKey(8)."\n";
$conf .= "address mqtt.jeedom.com:8883\n";
$conf .= "topic # both 0 ".$_local_topic."/ #cloud_username#/".$_remote_topic."/\n";
$conf .= "cleansession true\n";
$conf .= "notifications false\n";
$conf .= "remote_clientid cloud-#cloud_username#-jeedom-".config::genKey(8)."\n";
$conf .= "remote_username #cloud_username#\n";
$conf .= "remote_password #cloud_password#\n";
if(count($local_authentifications) == 2){
$conf .= "local_username ".$local_authentifications[0]."\n";
$conf .= "local_password ".$local_authentifications[1]."\n";
}
$conf .= "start_type automatic\n";
$conf .= "bridge_cafile ".__DIR__."/../config/ca_jeedom_cloud.crt\n";
$conf .= "# End autogenerate for ".$_local_topic." <-> cloud-".$_remote_topic."\n";
$current_conf = preg_replace('/(# Begin autogenerate for '.$_local_topic.' <-> cloud-'.$_remote_topic.')((.|\n)*)(# End autogenerate for '.$_local_topic.' <-> cloud-'.$_remote_topic.')/m', "", config::byKey('mosquitto::parameters', __CLASS__));
config::save('mosquitto::parameters', trim($current_conf)."\n\n".trim($conf), __CLASS__);
mqtt2::installMosquitto(config::byKey('mode', 'mqtt2'));
}

public static function syncTopicToLocalMqtt($_local_topic,$_remote_topic,$_username,$_password,$_ip,$_port = 1883){
if($_local_topic == '' || $_remote_topic == ''){
throw new Exception(__('Le local topic et le remonte ne peuvent etre vide',__FILE__));
}
if($_username == '' || $_password == ''){
throw new Exception(__('Le nom d\'utilisateur et le mot de passe ne peuvent etre vide',__FILE__));
}
if($_ip == ''){
throw new Exception(__('L\'ip ne peut etre vide',__FILE__));
}
$_local_topic = trim($_local_topic);
$_remote_topic = trim($_remote_topic);
$local_authentifications = explode(':', explode("\n", config::byKey('mqtt::password', __CLASS__))[0]);
$conf = "# Begin autogenerate for ".$_local_topic." <-> ".$_remote_topic."\n";
$conf .= "connection jeedom-".config::genKey(8)."\n";
$conf .= "address ".$_ip.":".$_port."\n";
$conf .= "topic # both 0 ".$_local_topic."/ ".$_remote_topic."/\n";
$conf .= "cleansession true\n";
$conf .= "notifications false\n";
$conf .= "remote_clientid jeedom-".config::genKey(8)."\n";
if($_username != '' && $_password != ''){
$conf .= "remote_username ".$_username."\n";
$conf .= "remote_password ".$_password."\n";
}
if(count($local_authentifications) == 2){
$conf .= "local_username ".$local_authentifications[0]."\n";
$conf .= "local_password ".$local_authentifications[1]."\n";
}
$conf .= "start_type automatic\n";
$conf .= "# End autogenerate for ".$_local_topic." <-> ".$_remote_topic."\n";
$current_conf = preg_replace('/(# Begin autogenerate for '.$_local_topic.' <-> '.$_remote_topic.')((.|\n)*)(# End autogenerate for '.$_local_topic.' <-> '.$_remote_topic.')/m', "", config::byKey('mosquitto::parameters', __CLASS__));
config::save('mosquitto::parameters', trim($current_conf)."\n\n".trim($conf), __CLASS__);
mqtt2::installMosquitto(config::byKey('mode', 'mqtt2'));
}

public static function cronDaily(){
self::sendBattery();
}
Expand Down Expand Up @@ -270,9 +352,15 @@ public static function installMosquitto($_mode = 'local') {
'/data/ssl/' => '/data/config/ssl/',
);
}

config::save('mosquitto::parameters', str_replace(array_keys($replace), $replace, config::byKey('mosquitto::parameters', __CLASS__)), __CLASS__);
//shell_exec(system::getCmdSudo() . ' chmod 777 '.__DIR__ . '/../../data/mosquitto.conf');
file_put_contents(__DIR__ . '/../../data/mosquitto.conf', str_replace("\r\n", "\n", config::byKey('mosquitto::parameters', __CLASS__)));
$replace = array(
"\r\n" => "\n",
'#cloud_username#' => mb_strtolower(config::byKey('market::username')),
'#cloud_password#' => config::byKey('market::password'),
);
shell_exec(system::getCmdSudo() . ' chmod 777 '.__DIR__ . '/../../data/mosquitto.conf');
file_put_contents(__DIR__ . '/../../data/mosquitto.conf', str_replace(array_keys($replace), $replace, config::byKey('mosquitto::parameters', __CLASS__)));
if ($_mode == 'docker') {
$docker->create();
} elseif (jeedom::getHardwareName() == 'docker') {
Expand Down Expand Up @@ -405,6 +493,9 @@ public static function deamon_info() {
}

public static function deamon_start() {
if(mqtt2::getPluginForTopic(config::byKey('root_topic', __CLASS__)) != __CLASS__){
throw new Exception(__('Le topic racine n\'est pas valide. Le topic racine ne peut etre identique à un topic ou un plugin est abonné.', __FILE__));
}
log::remove(__CLASS__ . '_update');
if (config::byKey('mode', __CLASS__, 'local') == 'local') {
if (shell_exec(system::getCmdSudo() . ' ps ax | grep mosquitto | grep mqtt2 | grep -v grep | wc -l') == 0) {
Expand All @@ -417,6 +508,7 @@ public static function deamon_start() {
if ($deamon_info['launchable'] != 'ok') {
throw new Exception(__('Veuillez vérifier la configuration', __FILE__));
}
self::createListenner();
if (config::byKey('mode', __CLASS__) == 'local' || config::byKey('mode', __CLASS__) == 'docker') {
$path_ssl = realpath(__DIR__ . '/../../data/ssl');
if (!file_exists($path_ssl . '/client.crt') || !file_exists($path_ssl . '/client.key') || filesize($path_ssl . '/client.crt') == 0 || filesize($path_ssl . '/client.key') == 0) {
Expand All @@ -440,8 +532,13 @@ public static function deamon_start() {
} else {
$cmd .= ' --mqtt_server ' . config::byKey('remote::protocol', __CLASS__) . '://' . config::byKey('remote::ip', __CLASS__) . ':' . config::byKey('remote::port', __CLASS__);
}
$cmd .= ' --username "' . $authentifications[0] . '"';
$cmd .= ' --password "' . $authentifications[1] . '"';
if (count($authentifications) != 2) {
$cmd .= ' --username ""';
$cmd .= ' --password ""';
}else {
$cmd .= ' --username "' . $authentifications[0] . '"';
$cmd .= ' --password "' . $authentifications[1] . '"';
}
$cmd .= ' --callback ' . network::getNetworkAccess('internal', 'http:127.0.0.1:port:comp') . '/plugins/mqtt2/core/php/jeeMqtt2.php';
$cmd .= ' --apikey ' . jeedom::getApiKey(__CLASS__);
$cmd .= ' --cycle ' . config::byKey('cycle', __CLASS__);
Expand Down Expand Up @@ -953,7 +1050,7 @@ public static function publish($_topic, $_message = '', $_options = array()) {
}

public static function handleEvent($_option) {
$cmd = cmd::byId($_option['event_id']);
$cmd = (isset($_option['object']) && is_object($_option['object'])) ? $_option['object'] : cmd::byId($_option['event_id']);
if (config::byKey('sendEvent', 'mqtt2', 0) == 0 && $cmd->getEqLogic()->getConfiguration('plugin::mqtt2::mqttTranmit', 0) == 0) {
return;
}
Expand Down Expand Up @@ -1038,8 +1135,8 @@ public static function sendDiscovery(){
if(isset($toSend['cmds'][$cmd->getId()]['configuration']['jeedomPreExecCmd'])){
unset($toSend['cmds'][$cmd->getId()]['configuration']['jeedomPreExecCmd']);
}
if (isset($_cmd['configuration']) && isset($_cmd['configuration']['calculValueOffset'])) {
unset($_cmd['configuration']['calculValueOffset']);
if(isset($toSend['cmds'][$cmd->getId()]['configuration']['calculValueOffset'])){
unset($toSend['cmds'][$cmd->getId()]['configuration']['calculValueOffset']);
}
}
self::publish(config::byKey('root_topic', __CLASS__) . '/discovery/eqLogic/'.$eqLogic->getId(), $toSend);
Expand All @@ -1054,7 +1151,8 @@ public static function sendDiscovery(){
foreach ($eqLogic->getCmd('info') as $cmd) {
self::handleEvent(array(
'event_id' => $cmd->getId(),
'value' => $cmd->execCmd()
'value' => $cmd->execCmd(),
'object' => $cmd
));
}
}
Expand Down Expand Up @@ -1158,6 +1256,7 @@ public static function jeedom_discovery($_topic,$_discovery) {
$cmd->setType('info');
$cmd->setSubType('string');
}
$cmd->setLogicalId('state');
$cmd->setEqType('mqtt2');
$cmd->setEqLogic_id($eqLogic->getId());
try {
Expand Down Expand Up @@ -1213,10 +1312,14 @@ public function applyCmdTemplate($_config) {
return;
}
$this->setConfiguration('device', $_config['template']);
if (isset($template['logicalId'])) {
$this->setLogicalId($template['logicalId']);
}
$config = array();
foreach ($_config as $key => $value) {
$config['#' . $key . '#'] = $value;
}
$link_cmds = array();
$cmds_template = json_decode(str_replace(($config), $config, json_encode($template['commands'])), true);
foreach ($cmds_template as $cmd_template) {
$cmd = new mqtt2Cmd();
Expand Down
22 changes: 22 additions & 0 deletions core/config/ca_jeedom_cloud.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqzCCApOgAwIBAgIUP5nJNi1fcCQvljKVZxFWA2lUNIowDQYJKoZIhvcNAQEL
BQAwZTELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTENMAsGA1UEBwwETHlv
bjEQMA4GA1UECgwHRG9tYWRvbzEPMA0GA1UECwwGSmVlZG9tMRMwEQYDVQQDDApq
ZWVkb20uY29tMB4XDTI0MDgyOTA3MTkyNloXDTI1MDgyOTA3MTkyNlowZTELMAkG
A1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTENMAsGA1UEBwwETHlvbjEQMA4GA1UE
CgwHRG9tYWRvbzEPMA0GA1UECwwGSmVlZG9tMRMwEQYDVQQDDApqZWVkb20uY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvki596Ak0Mknm56xgxQY
1pNOmMuCJqwufLqdJ59e/SzEYH+8jHY3JKSAGbfU06QB0Cq/pkuBJFCakX2ydLMC
AbLrMU+Su7u/vIbP1ZSLDa2D4ZFsvRUKIMCy6DPrHBwmAzfyMTaGcVyAoIzMzEff
RvHDnYurAT0gamTuFOdA7omuDUxipBVSyZ7DUpybeyFYC3+ikv7DLsnrT3tSw6eh
V8acbdz9iQjJaiZ7C4D1u/2z7EchZP9pPw6B97g792X5jD0yM31eeaiGin/oR3dj
9ufLG/z51ItVQqxuNibk7ZCr90rQIfExhSX7Bmq4TRs/VSqmmPQJ6VtZNCxsf7e2
zwIDAQABo1MwUTAdBgNVHQ4EFgQUXteHsWd1tcWoCH+dVPBvixXwpbowHwYDVR0j
BBgwFoAUXteHsWd1tcWoCH+dVPBvixXwpbowDwYDVR0TAQH/BAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAQEATLgI6PWO/G97mRHuISQruBk8MBvCsxq3OwU61j6m6JhS
WFTwMZzuTzIoTEoPyQXzM62bvJURIUjyP5R9uNxcdm3tFsZxOOiU0ElkGj+WwHfr
a/5pPL3wkFvvvRXmv4ZQhRJBwmA40kNITBqtPj+2dfgYP86FhLIDd/S1C1FqSJOV
MfTyLxaQcKfVbDNhgD0GunST2oV9O1skaMtYB4AULvWsknBxFE6TpuizdrKBERCQ
X1V6VHXP10i24E1KDZu4hhN/6Wu+qVYSUB0OyTCkUBMlA6pP2n030gHHSYjvD6C0
aEq23QREqR5cm524D+A5mTFrkuDGQbSjMuN+eNSzjQ==
-----END CERTIFICATE-----
86 changes: 86 additions & 0 deletions core/config/devices/jeedom/mosquitto.sys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"name" : "Mosquitto SYS",
"logicalId" : "$SYS/broker",
"commands" : [
{
"name": "Uptime",
"type": "info",
"subtype": "string",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "uptime"
},
{
"name": "Message reçu 1min",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "load/messages/received/1min"
},
{
"name": "Message reçu 5min",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "load/messages/received/5min"
},
{
"name": "Message reçu 15min",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "load/messages/received/15min"
},
{
"name": "Message envoyé 1min",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "load/messages/sent/1min"
},
{
"name": "Message envoyé 5min",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "load/messages/sent/5min"
},
{
"name": "Message envoyé 15min",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "load/messages/sent/15min"
},
{
"name": "Mémoire",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "heap/current"
},
{
"name": "Message envoyé",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "messages/sent"
},
{
"name": "Message reçu",
"type": "info",
"subtype": "numeric",
"isVisible": 1,
"isHistorized": 0,
"logicalId" : "messages/received"
}
]
}
3 changes: 0 additions & 3 deletions core/config/devices/jeedom/mqtt.json

This file was deleted.

7 changes: 5 additions & 2 deletions core/config/mqtt2.config.ini
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
[mqtt2]
autodiscovery=0
autodiscovery=1
socketport = 55035
cycle = 0.3
mode = local
root_topic = jeedom
qos::default = 0
mosquitto::ports="1883:1883
8883:8883"
mosquitto::parameters="per_listener_settings true
mosquitto::parameters="
log_dest file /var/log/mosquitto/mosquitto.log
per_listener_settings true
listener 1883
persistence false
Expand Down
Loading

0 comments on commit fe69694

Please sign in to comment.