iobroker.sbfspot 4.0.8 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,7 +28,7 @@ jobs:
28
28
  node-version: [12.x]
29
29
 
30
30
  steps:
31
- - uses: actions/checkout@v1
31
+ - uses: actions/checkout@v2
32
32
  - name: Use Node.js ${{ matrix.node-version }}
33
33
  uses: actions/setup-node@v1
34
34
  with:
@@ -51,14 +51,14 @@ jobs:
51
51
  runs-on: ${{ matrix.os }}
52
52
  strategy:
53
53
  matrix:
54
- node-version: [ 12.x, 14.x, 16.x]
54
+ node-version: [12.x, 14.x, 16.x]
55
55
  os: [ubuntu-latest, windows-latest, macos-latest]
56
56
  exclude:
57
57
  # Don't test Node.js 8 on Windows. npm is weird here
58
58
  - os: windows-latest
59
59
  node-version: 8.x
60
60
  steps:
61
- - uses: actions/checkout@v1
61
+ - uses: actions/checkout@v2
62
62
  - name: Use Node.js ${{ matrix.node-version }}
63
63
  uses: actions/setup-node@v1
64
64
  with:
@@ -78,7 +78,7 @@ jobs:
78
78
  if: startsWith(runner.OS, 'windows')
79
79
  run: set DEBUG=testing:* & npm run test:integration
80
80
 
81
- # TODO: To enable automatic npm releases, create a token on npmjs.org
81
+ # TODO: To enable automatic npm releases, create a token on npmjs.org
82
82
  # Enter this token as a GitHub secret (with name NPM_TOKEN) in the repository options
83
83
  # Then uncomment the following block:
84
84
 
@@ -90,6 +90,7 @@ jobs:
90
90
  # if: |
91
91
  # contains(github.event.head_commit.message, '[skip ci]') == false &&
92
92
  # github.event_name == 'push' &&
93
+ # github.event.base_ref == 'refs/heads/master' &&
93
94
  # startsWith(github.ref, 'refs/tags/v')
94
95
  #
95
96
  # runs-on: ubuntu-latest
@@ -98,7 +99,7 @@ jobs:
98
99
  # node-version: [12.x]
99
100
  #
100
101
  # steps:
101
- # - uses: actions/checkout@v1
102
+ # - uses: actions/checkout@v2
102
103
  # - name: Use Node.js ${{ matrix.node-version }}
103
104
  # uses: actions/setup-node@v1
104
105
  # with:
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) <2017-2021> <info@rg-engineering.eu>
1
+ Copyright (C) <2017-2022> <info@rg-engineering.eu>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
package/README.md CHANGED
@@ -51,6 +51,9 @@ sometimes npm intall must be called more then one time to successfully install a
51
51
 
52
52
  ## Changelog
53
53
 
54
+ ### 4.1.0 (2022-04-21)
55
+ * (René) add datapoint to show when data uploaded to sbfspot
56
+
54
57
  ### 4.0.8 (2021-07-11)
55
58
  * (René) bug fix color of labels in widget
56
59
 
@@ -182,7 +185,7 @@ sometimes npm intall must be called more then one time to successfully install a
182
185
 
183
186
 
184
187
  ## License
185
- Copyright (C) <2017-2021> <info@rg-engineering.eu>
188
+ Copyright (C) <2017-2022> <info@rg-engineering.eu>
186
189
 
187
190
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
188
191
 
package/io-package.json CHANGED
@@ -1,8 +1,20 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "sbfspot",
4
- "version": "4.0.8",
4
+ "version": "4.1.0",
5
5
  "news": {
6
+ "4.1.0": {
7
+ "en": "add datapoint to show when data uploaded to sbfspot",
8
+ "de": "Datenpunkt hinzufügen, um anzuzeigen, wann Daten auf sbfspot hochgeladen wurden",
9
+ "ru": "добавить точку данных, чтобы показать, когда данные загружаются в sbfspot",
10
+ "pt": "adicionar ponto de dados para mostrar quando os dados são carregados no sbfspot",
11
+ "nl": "voeg datapunt toe om te laten zien wanneer gegevens zijn geüpload naar sbfspot",
12
+ "fr": "ajouter un point de données pour montrer quand les données sont téléchargées sur sbfspot",
13
+ "it": "aggiungi datapoint per mostrare quando i dati sono stati caricati su sbfspot",
14
+ "es": "agregue un punto de datos para mostrar cuándo se cargan los datos en sbfspot",
15
+ "pl": "dodaj punkt danych, aby pokazać, kiedy dane zostały przesłane do sbfspot",
16
+ "zh-cn": "添加数据点以显示何时将数据上传到 sbfspot"
17
+ },
6
18
  "4.0.8": {
7
19
  "en": "bug fix color of labels in widget",
8
20
  "de": "Fehlerkorrektur Farbe der Labels im Widget",
package/lib/tools.js CHANGED
@@ -56,7 +56,7 @@ async function translateYandex(text, targetLang, apiKey) {
56
56
  }
57
57
  try {
58
58
  const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apiKey}&text=${encodeURIComponent(text)}&lang=en-${targetLang}`;
59
- const response = await axios({url, timeout: 15000});
59
+ const response = await axios({ url, timeout: 15000 });
60
60
  if (response.data && response.data.text && isArray(response.data.text)) {
61
61
  return response.data.text[0];
62
62
  }
@@ -75,7 +75,7 @@ async function translateYandex(text, targetLang, apiKey) {
75
75
  async function translateGoogle(text, targetLang) {
76
76
  try {
77
77
  const url = `http://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}&ie=UTF-8&oe=UTF-8`;
78
- const response = await axios({url, timeout: 15000});
78
+ const response = await axios({ url, timeout: 15000 });
79
79
  if (isArray(response.data)) {
80
80
  // we got a valid response
81
81
  return response.data[0][0][0];
package/main.js CHANGED
@@ -15,8 +15,12 @@ Copyright(C)[2016-2020][René Glaß]
15
15
  "use strict";
16
16
 
17
17
  const utils = require("@iobroker/adapter-core");
18
+ //const { json } = require("stream/consumers");
18
19
  const SunCalc = require("suncalc2");
19
20
 
21
+
22
+
23
+
20
24
  let adapter;
21
25
  function startAdapter(options) {
22
26
  options = options || {};
@@ -110,6 +114,7 @@ async function main() {
110
114
 
111
115
  await GetInverter(i, rows);
112
116
 
117
+ await DB_CheckLastUploads(serial);
113
118
 
114
119
  let rows1 = await DB_GetInvertersData(serial);
115
120
 
@@ -151,12 +156,8 @@ async function main() {
151
156
  }
152
157
 
153
158
  }
154
-
155
159
  }
156
-
157
-
158
160
  }
159
-
160
161
  }
161
162
  } else {
162
163
  //
@@ -165,8 +166,6 @@ async function main() {
165
166
  }
166
167
  }
167
168
  DB_Disconnect();
168
-
169
-
170
169
  }
171
170
  else {
172
171
  adapter.log.info("nothing to do, because no daylight ... ");
@@ -185,18 +184,23 @@ async function main() {
185
184
  }
186
185
 
187
186
  async function GetSystemDateformat() {
188
- const ret = await adapter.getForeignObjectAsync("system.config");
189
-
190
- if (typeof ret != undefined && ret != null) {
191
- //dateformat = ret.common.dateFormat;
192
- longitude = ret.common.longitude;
193
- latitude = ret.common.latitude;
194
- adapter.log.debug("system longitude " + longitude + " latitude " + latitude);
187
+ try {
188
+ const ret = await adapter.getForeignObjectAsync("system.config");
189
+
190
+ if (typeof ret != undefined && ret != null) {
191
+ //dateformat = ret.common.dateFormat;
192
+ longitude = ret.common.longitude;
193
+ latitude = ret.common.latitude;
194
+ adapter.log.debug("system: longitude " + longitude + " latitude " + latitude);
195
+ }
196
+ else {
197
+ adapter.log.error("system.config not available. longitude and latitude set to Berlin");
198
+ longitude = 52.520008;
199
+ latitude = 13.404954;
200
+ }
195
201
  }
196
- else {
197
- adapter.log.error("system.config not available. longitude and latitude set to Berlin");
198
- longitude = 52.520008;
199
- latitude = 13.404954;
202
+ catch (e) {
203
+ adapter.log.error("exception in GetSystemDateformat [" + e + "]");
200
204
  }
201
205
  }
202
206
 
@@ -324,6 +328,9 @@ async function AddInverterVariables(serial) {
324
328
  await AddObject(serial.toString() + ".history.last12Months", "state", "SMA inverter history last 12 Months (JSON)", "string", "value", "", true, false);
325
329
  await AddObject(serial.toString() + ".history.years", "state", "SMA inverter history years (JSON)", "string", "value", "", true, false);
326
330
 
331
+ await AddObject(serial.toString() + ".sbfspot.LastUpload", "state", "date/time of last upload to sbfspot", "string", "value", "", true, false);
332
+ await AddObject(serial.toString() + ".sbfspot.notUploaded", "state", "number of datapoints waiting for upload", "number", "value", "", true, false);
333
+
327
334
 
328
335
  adapter.log.debug("AddInverterVariables done " );
329
336
  }
@@ -467,49 +474,78 @@ async function DB_Connect() {
467
474
  return ret;
468
475
  }
469
476
 
477
+ async function DB_Query(query) {
478
+
479
+ adapter.log.debug(query);
480
+ let retRows;
470
481
 
482
+ if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
471
483
 
484
+ const [rows, fields] = await mysql_connection.execute(query);
485
+ retRows = rows;
472
486
 
487
+ } else {
488
+ const stmt = sqlite_db.prepare(query);
473
489
 
474
- async function DB_GetInverters() {
490
+ const rows = stmt.all();
491
+ retRows = rows;
492
+ }
493
+
494
+ adapter.log.debug(JSON.stringify(retRows));
495
+
496
+ return retRows;
497
+ }
498
+
499
+ async function DB_CheckLastUploads(serial) {
475
500
 
476
- let retRows;
477
501
  try {
478
- const query = "SELECT * from Inverters";
479
- //numOfInverters = 0;
480
- adapter.log.debug(query);
502
+ let query = "SELECT `TimeStamp` FROM `DayData` WHERE `PVoutput` is null ";
481
503
 
504
+ let rows = await DB_Query(query);
482
505
 
506
+ let notUploaded = rows.length;
483
507
 
484
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
508
+ await adapter.setStateAsync(serial + ".sbfspot.notUploaded", { ack: true, val: notUploaded });
485
509
 
486
- const [rows, fields] = await mysql_connection.execute(query);
510
+ query = "SELECT `TimeStamp` FROM `DayData` WHERE `PVoutput` = 1 ORDER BY TimeStamp DESC LIMIT 1 ";
487
511
 
488
- retRows = rows;
512
+ rows = await DB_Query(query);
489
513
 
490
- //await GetInverter(0, rows);
514
+ if (rows.length > 0) {
515
+ let updateTimestamp = rows[0].TimeStamp;
516
+ const oDate = new Date(updateTimestamp * 1000);
517
+ const oDateNow = new Date();
491
518
 
492
-
493
- } else {
519
+ oDateNow.setDate(oDateNow.getDate() - 1);
494
520
 
495
- const stmt = sqlite_db.prepare(query);
496
521
 
497
- const rows = stmt.all();
498
- retRows = rows;
499
- //await GetInverter(0, rows);
522
+ if (oDate < oDateNow) {
523
+ adapter.log.error("no upload to sbfspot since " + oDate.toLocaleString());
524
+ }
525
+
526
+ let lastUpload = oDate.toLocaleString();
500
527
 
501
-
528
+ await adapter.setStateAsync(serial + ".sbfspot.LastUpload", { ack: true, val: lastUpload });
502
529
  }
530
+ }
531
+ catch (e) {
532
+ adapter.log.error("exception in DB_CheckLastUploads [" + e + "]");
533
+ }
534
+ }
503
535
 
504
-
505
536
 
506
537
 
538
+ async function DB_GetInverters() {
539
+
540
+ let retRows;
541
+ try {
542
+ const query = "SELECT * from Inverters";
543
+ retRows = await DB_Query(query);
507
544
  }
508
545
  catch (e) {
509
546
  adapter.log.error("exception in DB_GetInverters [" + e + "]");
510
547
  }
511
548
 
512
-
513
549
  return retRows;
514
550
  }
515
551
 
@@ -574,28 +610,7 @@ async function DB_GetInvertersData(serial) {
574
610
  try {
575
611
  //SELECT * from SpotData where Serial ='2000562095' ORDER BY TimeStamp DESC LIMIT 1
576
612
  const query = "SELECT * from SpotData where Serial =" + serial + " ORDER BY TimeStamp DESC LIMIT 1";
577
- adapter.log.debug(query);
578
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
579
- //we only get one row = last one
580
-
581
- const [rows, fields] = await mysql_connection.execute(query);
582
-
583
- retRows = rows;
584
- //await GetInverterData(0, rows, serial);
585
-
586
-
587
- } else {
588
-
589
- const stmt = sqlite_db.prepare(query);
590
-
591
- const rows = stmt.all();
592
-
593
- retRows = rows;
594
-
595
- //await GetInverterData(0, rows, serial);
596
-
597
-
598
- }
613
+ retRows = await DB_Query(query);
599
614
  }
600
615
  catch (e) {
601
616
  adapter.log.error("exception in DB_GetInvertersData [" + e + "]");
@@ -701,25 +716,7 @@ async function DB_CalcHistory_LastMonth(serial) {
701
716
  } else {
702
717
  query = "SELECT strftime('%Y-%m-%d', datetime(TimeStamp, 'unixepoch')) as date, Max(`EToday`) as ertrag FROM `SpotData` WHERE `Serial` = '" + serial + "' AND TimeStamp>= " + datefrom.getTime() / 1000 + " AND TimeStamp<= " + dateto.getTime() / 1000 + " Group By strftime('%Y-%m-%d', datetime(TimeStamp, 'unixepoch'))";
703
718
  }
704
- adapter.log.debug(query);
705
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
706
-
707
- const [rows, fields] = await mysql_connection.execute(query);
708
-
709
- retRows = rows;
710
- //await calcHistory_LastMonth(0, rows, serial);
711
-
712
-
713
- } else {
714
-
715
- const stmt = sqlite_db.prepare(query);
716
-
717
- const rows = stmt.all();
718
- retRows = rows;
719
- //await CalcHistory_LastMonth(0, rows, serial);
720
-
721
-
722
- }
719
+ retRows = await DB_Query(query);
723
720
  }
724
721
  catch (e) {
725
722
  adapter.log.error("exception in DB_CalcHistory_LastMonth [" + e + "]");
@@ -784,26 +781,7 @@ async function DB_CalcHistory_Prepare(serial) {
784
781
  } else {
785
782
  query = "SELECT strftime('%Y-%m-%d', datetime(TimeStamp, 'unixepoch')) as date, ETotal FROM `SpotData` WHERE `Serial` = '" + serial + "' ORDER by `TimeStamp` ASC LIMIT 1";
786
783
  }
787
- adapter.log.debug(query);
788
-
789
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
790
-
791
- const [rows, fields] = await mysql_connection.execute(query);
792
-
793
- retRows = rows;
794
- //await CalcHistory_Prepare(0, rows, serial);
795
-
796
-
797
- } else {
798
-
799
-
800
- const stmt = sqlite_db.prepare(query);
801
-
802
- const rows = stmt.all();
803
- retRows = rows;
804
- //await CalcHistory_Prepare(0, rows, serial);
805
-
806
- }
784
+ retRows = await DB_Query(query);
807
785
  }
808
786
  catch (e) {
809
787
  adapter.log.error("exception in DB_CalcHistory_Prepare [" + e + "]");
@@ -860,25 +838,7 @@ async function DB_CalcHistory_Today(serial) {
860
838
  } else {
861
839
  query = "SELECT strftime('%H:%m', datetime(TimeStamp, 'unixepoch')) as time, Max(`EToday`) as ertrag FROM `SpotData` WHERE `Serial` = '" + serial + "' AND TimeStamp>= " + datefrom.getTime() / 1000 + " AND TimeStamp<= " + dateto.getTime() / 1000 + " Group By strftime('%H-%m', datetime(TimeStamp, 'unixepoch'))";
862
840
  }
863
- adapter.log.debug(query);
864
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
865
-
866
- const [rows, fields] = await mysql_connection.execute(query);
867
- retRows = rows;
868
-
869
- //await CalcHistory_Today(0, rows, serial);
870
-
871
-
872
- } else {
873
-
874
- const stmt = sqlite_db.prepare(query);
875
-
876
- const rows = stmt.all();
877
- retRows = rows;
878
- //await CalcHistory_Today(0, rows, serial);
879
-
880
-
881
- }
841
+ retRows = await DB_Query(query);
882
842
  }
883
843
  catch (e) {
884
844
  adapter.log.error("exception in DB_CalcHistory_Today [" + e + "]");
@@ -908,12 +868,11 @@ async function CalcHistory_Today(err, rows, serial) {
908
868
  "time": data["time"],
909
869
  "value": data["ertrag"]
910
870
  });
911
- //adapter.log.debug(JSON.stringify(oLastDays));
871
+
912
872
  }
913
873
 
914
874
  await adapter.setStateAsync(serial + ".history.today", { ack: true, val: JSON.stringify(oLastDays) });
915
875
 
916
- //await DB_CalcHistory_Years(serial);
917
876
  } else {
918
877
  adapter.log.error("Error while performing Query in CalcHistory_Today. " + err);
919
878
  }
@@ -937,27 +896,7 @@ async function DB_CalcHistory_Years(serial) {
937
896
  } else {
938
897
  query = "SELECT strftime('%Y', datetime(TimeStamp, 'unixepoch')) as date, Max(`ETotal`) as ertrag, Min(`ETotal`) as startertrag FROM `SpotData` WHERE `Serial` = '" + serial + "' Group By strftime('%Y', datetime(TimeStamp, 'unixepoch'))";
939
898
  }
940
- adapter.log.debug(query);
941
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
942
-
943
- const [rows, fields] = await mysql_connection.execute(query);
944
-
945
- retRows = rows;
946
- //await CalcHistory_Years(0, rows, serial);
947
-
948
-
949
- } else {
950
-
951
- const stmt = sqlite_db.prepare(query);
952
-
953
- const rows = stmt.all();
954
- retRows = rows;
955
-
956
- //await CalcHistory_Years(0, rows, serial);
957
-
958
-
959
-
960
- }
899
+ retRows = await DB_Query(query);
961
900
  }
962
901
  catch (e) {
963
902
  adapter.log.error("exception in DB_CalcHistory_Years [" + e + "]");
@@ -1053,7 +992,6 @@ async function CalcHistory_Years(err, rows, serial) {
1053
992
  adapter.log.debug(JSON.stringify(oLastYears));
1054
993
  await adapter.setStateAsync(serial + ".history.years", { ack: true, val: JSON.stringify(oLastYears) });
1055
994
 
1056
- //await DB_CalcHistory_Months(serial);
1057
995
  } else {
1058
996
  adapter.log.error("Error while performing Query in CalcHistory_Years. " + err);
1059
997
  }
@@ -1086,24 +1024,7 @@ async function DB_CalcHistory_Months(serial) {
1086
1024
  } else {
1087
1025
  query = "SELECT strftime('%Y-%m', datetime(TimeStamp, 'unixepoch')) as date, Max(`ETotal`) as ertrag FROM `SpotData` WHERE `Serial` = '" + serial + "' AND TimeStamp>= " + datefrom.getTime() / 1000 + " AND TimeStamp<= " + dateto.getTime() / 1000 + " Group By strftime('%Y-%m', datetime(TimeStamp, 'unixepoch'))";
1088
1026
  }
1089
- adapter.log.debug(query);
1090
- if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
1091
-
1092
- const [rows, fields] = await mysql_connection.execute(query);
1093
- retRows = rows;
1094
- //await CalcHistory_Months(0, rows, serial);
1095
-
1096
-
1097
- } else {
1098
-
1099
- const stmt = sqlite_db.prepare(query);
1100
-
1101
- const rows = stmt.all();
1102
- retRows = rows;
1103
- //await CalcHistory_Months(0, rows, serial);
1104
-
1105
-
1106
- }
1027
+ retRows = await DB_Query(query);
1107
1028
  }
1108
1029
  catch (e) {
1109
1030
  adapter.log.error("exception in DB_CalcHistory_Months [" + e + "]");
@@ -1122,7 +1043,6 @@ async function CalcHistory_Months(err, rows, serial) {
1122
1043
  adapter.log.debug("rows " + JSON.stringify(rows));
1123
1044
 
1124
1045
  const oLastMonth = [];
1125
- //var monthdata = {};
1126
1046
 
1127
1047
  for (const i in rows) {
1128
1048
 
@@ -1132,12 +1052,11 @@ async function CalcHistory_Months(err, rows, serial) {
1132
1052
  "month": data["date"],
1133
1053
  "value": data["ertrag"]
1134
1054
  });
1135
- //adapter.log.debug(JSON.stringify(oLastDays));
1055
+
1136
1056
  }
1137
1057
 
1138
1058
  await adapter.setStateAsync(serial + ".history.last12Months", { ack: true, val: JSON.stringify(oLastMonth) });
1139
1059
 
1140
- //DB_Disconnect();
1141
1060
  } else {
1142
1061
  adapter.log.error("Error while performing Query in CalcHistory_Months. " + err);
1143
1062
  }
@@ -1189,10 +1108,6 @@ async function DB_AddDummyData() {
1189
1108
 
1190
1109
  function DB_Disconnect() {
1191
1110
 
1192
- //numOfInverters--;
1193
- // wait for all data paths... last data path will close connection
1194
-
1195
- //if (numOfInverters == 0) {
1196
1111
  adapter.log.debug("disconnect database");
1197
1112
  if (adapter.config.databasetype == "mySQL" || adapter.config.databasetype == "MariaDB") {
1198
1113
  if (typeof mysql_connection != undefined && mysql_connection != null) {
@@ -1205,124 +1120,10 @@ function DB_Disconnect() {
1205
1120
  }
1206
1121
 
1207
1122
  adapter.log.info("all done ... ");
1208
-
1209
-
1210
- //} else {
1211
- // adapter.log.debug("need to wait for disconnect");
1212
- //}
1213
- }
1214
-
1215
-
1216
- /**
1217
- * @param {string} timeVal
1218
- * @param {string} timeLimit
1219
- */
1220
- /*
1221
- function IsLater(timeVal, timeLimit) {
1222
-
1223
- let ret = false;
1224
- try {
1225
- adapter.log.debug("check IsLater : " + timeVal + " " + timeLimit);
1226
-
1227
- if (typeof timeVal === "string" && typeof timeLimit === "string") {
1228
- const valIn = timeVal.split(":");
1229
- const valLimits = timeLimit.split(":");
1230
-
1231
- if (valIn.length > 1 && valLimits.length > 1) {
1232
-
1233
- if (parseInt(valIn[0]) > parseInt(valLimits[0])
1234
- || (parseInt(valIn[0]) == parseInt(valLimits[0]) && parseInt(valIn[1]) > parseInt(valLimits[1]))) {
1235
- ret = true;
1236
- adapter.log.debug("yes, IsLater : " + timeVal + " " + timeLimit);
1237
- }
1238
- }
1239
- else {
1240
- adapter.log.error("string does not contain : " + timeVal + " " + timeLimit);
1241
- }
1242
- }
1243
- else {
1244
- adapter.log.error("not a string " + typeof timeVal + " " + typeof timeLimit);
1245
- }
1246
- }
1247
- catch (e) {
1248
- adapter.log.error("exception in IsLater [" + e + "]");
1249
- }
1250
- return ret;
1251
- }
1252
- */
1253
- /**
1254
- * @param {string } timeVal
1255
- * @param {string } [timeLimit]
1256
- */
1257
- /*
1258
- function IsEarlier(timeVal, timeLimit) {
1259
-
1260
- let ret = false;
1261
- try {
1262
- adapter.log.debug("check IsEarlier : " + timeVal + " " + timeLimit);
1263
-
1264
- if (typeof timeVal === "string" && typeof timeLimit === "string") {
1265
- const valIn = timeVal.split(":");
1266
- const valLimits = timeLimit.split(":");
1267
-
1268
- if (valIn.length > 1 && valLimits.length > 1) {
1269
-
1270
- if (parseInt(valIn[0]) < parseInt(valLimits[0])
1271
- || (parseInt(valIn[0]) == parseInt(valLimits[0]) && parseInt(valIn[1]) < parseInt(valLimits[1]))) {
1272
- ret = true;
1273
- adapter.log.debug("yes, IsEarlier : " + timeVal + " " + timeLimit);
1274
- }
1275
- }
1276
- else {
1277
- adapter.log.error("string does not contain : " + timeVal + " " + timeLimit);
1278
- }
1279
- }
1280
- else {
1281
- adapter.log.error("not a string " + typeof timeVal + " " + typeof timeLimit);
1282
- }
1283
- }
1284
- catch (e) {
1285
- adapter.log.error("exception in IsEarlier [" + e + "]");
1286
- }
1287
- return ret;
1288
1123
  }
1289
- */
1290
- /**
1291
- * @param {string} timeVal
1292
- * @param {string} timeLimit
1293
- */
1294
- /*
1295
- function IsEqual(timeVal, timeLimit) {
1296
-
1297
- let ret = false;
1298
- try {
1299
- adapter.log.debug("check IsEqual : " + timeVal + " " + timeLimit);
1300
1124
 
1301
- if (typeof timeVal === "string" && typeof timeLimit === "string") {
1302
- const valIn = timeVal.split(":");
1303
- const valLimits = timeLimit.split(":");
1304
1125
 
1305
- if (valIn.length > 1 && valLimits.length > 1) {
1306
1126
 
1307
- if (parseInt(valIn[0]) === parseInt(valLimits[0]) && parseInt(valIn[1]) === parseInt(valLimits[1])) {
1308
- ret = true;
1309
- adapter.log.debug("yes, IsEqual : " + timeVal + " " + timeLimit);
1310
- }
1311
- }
1312
- else {
1313
- adapter.log.error("string does not contain : " + timeVal + " " + timeLimit);
1314
- }
1315
- }
1316
- else {
1317
- adapter.log.error("not a string " + typeof timeVal + " " + typeof timeLimit);
1318
- }
1319
- }
1320
- catch (e) {
1321
- adapter.log.error("exception in IsEqual [" + e + "]");
1322
- }
1323
- return ret;
1324
- }
1325
- */
1326
1127
 
1327
1128
  // If started as allInOne/compact mode => return function to create instance
1328
1129
  if (module && module.parent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.sbfspot",
3
- "version": "4.0.8",
3
+ "version": "4.1.0",
4
4
  "description": "sbfspot (SMA inverter) Adapter",
5
5
  "author": {
6
6
  "name": "René G.",
@@ -18,31 +18,31 @@
18
18
  "url": "https://github.com/rg-engineering/ioBroker.sbfspot"
19
19
  },
20
20
  "dependencies": {
21
- "@iobroker/adapter-core": "2.5.1",
22
- "@sentry/node": "6.14.1",
23
- "better-sqlite3": "7.4.4",
24
- "mysql2": "2.3.2",
21
+ "@iobroker/adapter-core": "2.6.0",
22
+ "@sentry/node": "6.19.6",
23
+ "better-sqlite3": "7.5.1",
24
+ "mysql2": "2.3.3",
25
25
  "suncalc2": "1.8.1"
26
26
  },
27
27
  "devDependencies": {
28
- "@iobroker/testing": "2.5.2",
29
- "@types/chai": "4.2.22",
30
- "@types/chai-as-promised": "7.1.4",
28
+ "@iobroker/testing": "2.6.0",
29
+ "@types/chai": "4.3.1",
30
+ "@types/chai-as-promised": "7.1.5",
31
31
  "@types/gulp": "4.0.9",
32
- "@types/mocha": "9.0.0",
33
- "@types/node": "16.11.6",
32
+ "@types/mocha": "9.1.1",
33
+ "@types/node": "17.0.25",
34
34
  "@types/proxyquire": "1.3.28",
35
35
  "@types/request-promise-native": "1.0.18",
36
- "@types/sinon": "10.0.6",
37
- "@types/sinon-chai": "3.2.5",
38
- "axios": "0.24.0",
39
- "chai": "4.3.4",
36
+ "@types/sinon": "10.0.11",
37
+ "@types/sinon-chai": "3.2.8",
38
+ "axios": "0.26.1",
39
+ "chai": "4.3.6",
40
40
  "chai-as-promised": "7.1.1",
41
- "eslint": "8.1.0",
41
+ "eslint": "8.13.0",
42
42
  "gulp": "4.0.2",
43
- "mocha": "9.1.3",
43
+ "mocha": "9.2.2",
44
44
  "proxyquire": "2.1.3",
45
- "sinon": "12.0.1",
45
+ "sinon": "13.0.2",
46
46
  "sinon-chai": "3.7.0"
47
47
  },
48
48
  "main": "main.js",
package/sbfspot.njsproj CHANGED
@@ -50,6 +50,9 @@
50
50
  <Content Include="docs\en\install_arm.md">
51
51
  <SubType>Code</SubType>
52
52
  </Content>
53
+ <Content Include="lib\tools.js">
54
+ <SubType>Code</SubType>
55
+ </Content>
53
56
  <Content Include="LICENSE" />
54
57
  <Content Include="package-lock.json" />
55
58
  <Content Include="readme.txt" />
@@ -59,7 +62,6 @@
59
62
  <Content Include="package.json" />
60
63
  <Content Include="README.md" />
61
64
  <Content Include="admin\index.html" />
62
- <Compile Include="lib\utils.js" />
63
65
  <Compile Include="tasks\jscs.js" />
64
66
  <Compile Include="tasks\jscsRules.js" />
65
67
  <Compile Include="tasks\jshint.js" />
@@ -111,8 +113,8 @@
111
113
  <Folder Include="admin\i18n\pt\" />
112
114
  <Folder Include="admin\i18n\ru\" />
113
115
  <Folder Include="docs\en\" />
114
- <Folder Include="lib" />
115
116
  <Folder Include="docs\" />
117
+ <Folder Include="lib\" />
116
118
  <Folder Include="tasks" />
117
119
  <Folder Include="test\" />
118
120
  <Folder Include="typings\" />
@@ -1,371 +0,0 @@
1
- "use strict";
2
-
3
- const heatingcontrolDictionary = require("./vis_words.js").heatingcontrolDictionary;
4
-
5
- /**
6
- * @param {string} timeVal
7
- * @param {string} timeLimit
8
- */
9
- function IsLater(adapter, timeVal, timeLimit) {
10
-
11
- let ret = false;
12
- try {
13
- adapter.log.debug("check IsLater : " + timeVal + " " + timeLimit);
14
-
15
- if (typeof timeVal === "string" && typeof timeLimit === "string") {
16
- const valIn = timeVal.split(":");
17
- const valLimits = timeLimit.split(":");
18
-
19
- if (valIn.length > 1 && valLimits.length > 1) {
20
-
21
- if (parseInt(valIn[0]) > parseInt(valLimits[0])
22
- || (parseInt(valIn[0]) == parseInt(valLimits[0]) && parseInt(valIn[1]) > parseInt(valLimits[1]))) {
23
- ret = true;
24
- adapter.log.debug("yes, IsLater : " + timeVal + " " + timeLimit);
25
- }
26
- }
27
- else {
28
- adapter.log.error("string does not contain : " + timeVal + " " + timeLimit);
29
- }
30
- }
31
- else {
32
- adapter.log.error("not a string " + typeof timeVal + " " + typeof timeLimit);
33
- }
34
- }
35
- catch (e) {
36
- adapter.log.error("exception in IsLater [" + e + "]");
37
- }
38
- return ret;
39
- }
40
-
41
- /**
42
- * @param {string } timeVal
43
- * @param {string } [timeLimit]
44
- */
45
- function IsEarlier(adapter, timeVal, timeLimit) {
46
-
47
- let ret = false;
48
- try {
49
- adapter.log.debug("check IsEarlier : " + timeVal + " " + timeLimit);
50
-
51
- if (typeof timeVal === "string" && typeof timeLimit === "string") {
52
- const valIn = timeVal.split(":");
53
- const valLimits = timeLimit.split(":");
54
-
55
- if (valIn.length > 1 && valLimits.length > 1) {
56
-
57
- if (parseInt(valIn[0]) < parseInt(valLimits[0])
58
- || (parseInt(valIn[0]) == parseInt(valLimits[0]) && parseInt(valIn[1]) < parseInt(valLimits[1]))) {
59
- ret = true;
60
- adapter.log.debug("yes, IsEarlier : " + timeVal + " " + timeLimit);
61
- }
62
- }
63
- else {
64
- adapter.log.error("string does not contain : " + timeVal + " " + timeLimit);
65
- }
66
- }
67
- else {
68
- adapter.log.error("not a string " + typeof timeVal + " " + typeof timeLimit);
69
- }
70
- }
71
- catch (e) {
72
- adapter.log.error("exception in IsEarlier [" + e + "]");
73
- }
74
- return ret;
75
- }
76
-
77
- /**
78
- * @param {string} timeVal
79
- * @param {string} timeLimit
80
- */
81
- function IsEqual(adapter, timeVal, timeLimit) {
82
-
83
- let ret = false;
84
- try {
85
- adapter.log.debug("check IsEqual : " + timeVal + " " + timeLimit);
86
-
87
- if (typeof timeVal === "string" && typeof timeLimit === "string") {
88
- const valIn = timeVal.split(":");
89
- const valLimits = timeLimit.split(":");
90
-
91
- if (valIn.length > 1 && valLimits.length > 1) {
92
-
93
- if (parseInt(valIn[0]) === parseInt(valLimits[0]) && parseInt(valIn[1]) === parseInt(valLimits[1])) {
94
- ret = true;
95
- adapter.log.debug("yes, IsEqual : " + timeVal + " " + timeLimit);
96
- }
97
- }
98
- else {
99
- adapter.log.error("string does not contain : " + timeVal + " " + timeLimit);
100
- }
101
- }
102
- else {
103
- adapter.log.error("not a string " + typeof timeVal + " " + typeof timeLimit);
104
- }
105
- }
106
- catch (e) {
107
- adapter.log.error("exception in IsEqual [" + e + "]");
108
- }
109
- return ret;
110
- }
111
-
112
- //*******************************************************************
113
- //
114
- // find a object in array by key and value
115
- // returns the object
116
- function findObjectByKey(array, key, value) {
117
- if (array !== null && typeof array !== undefined) {
118
- for (let i = 0; i < array.length; i++) {
119
- if (array[i][key] === value) {
120
- return array[i];
121
- }
122
- }
123
- }
124
- return null;
125
- }
126
-
127
- //*******************************************************************
128
- //
129
- // find a object in array by key and value
130
- // returns the object
131
- function findObjectsByKey(array, key, value) {
132
-
133
- const ret = [];
134
-
135
- if (array !== null && typeof array !== undefined) {
136
- for (let i = 0; i < array.length; i++) {
137
- if (array[i][key] === value) {
138
- ret.push(array[i]);
139
- }
140
- }
141
- }
142
- return ret;
143
- }
144
-
145
-
146
- //*******************************************************************
147
- //
148
- // find a object in array by key and value
149
- // returns index number
150
- function findObjectIdByKey(array, key, value) {
151
-
152
-
153
- //array.filter(d => d.key == value);
154
-
155
- if (array !== null && typeof array !== undefined) {
156
-
157
- for (let i = 0; i < array.length; i++) {
158
- if (array[i][key] === value) {
159
- return i;
160
- }
161
- }
162
- }
163
- return -1;
164
- }
165
-
166
-
167
- //*******************************************************************
168
- //
169
- // find all objects in array by key and value
170
- // returns index number array
171
- function findObjectsIdByKey(array, key, value) {
172
-
173
- const ret = [];
174
-
175
- if (array !== null && typeof array !== undefined) {
176
-
177
- for (let i = 0; i < array.length; i++) {
178
- if (array[i][key] === value) {
179
- ret.push(i);
180
- }
181
- }
182
- }
183
- return ret;
184
- }
185
-
186
-
187
- function timeConverter(SystemLanguage,time, timeonly = false) {
188
-
189
- let a;
190
-
191
- if (time != null) {
192
- a = new Date(time);
193
- }
194
- else {
195
- a = new Date();
196
- }
197
- let months;
198
-
199
- if (SystemLanguage === "de") {
200
- months = ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
201
- }
202
- else {
203
- months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
204
- }
205
- const year = a.getFullYear();
206
- const month = months[a.getMonth()];
207
- let date = a.getDate();
208
- date = date < 10 ? " " + date : date;
209
- let hour = a.getHours();
210
- hour = hour < 10 ? "0" + hour : hour;
211
- let min = a.getMinutes();
212
- min = min < 10 ? "0" + min : min;
213
- let sec = a.getSeconds();
214
- sec = sec < 10 ? "0" + sec : sec;
215
-
216
- let sRet = "";
217
- if (timeonly) {
218
- sRet = hour + ":" + min + ":" + sec;
219
- }
220
- else {
221
- sRet = date + " " + month + " " + year + " " + hour + ":" + min + ":" + sec;
222
- }
223
-
224
- return sRet;
225
- }
226
-
227
- function CheckValidTime(adapter, id, time) {
228
-
229
- let sRet = "00:00";
230
- try {
231
- if (time === "null" || typeof time === undefined) {
232
- adapter.log.error("time value not found for " + id);
233
-
234
- }
235
- else if (typeof time !== "string") {
236
- adapter.log.error("time should be a string but is " + typeof time.val + " for " + id);
237
-
238
- }
239
- else if (time.length < 3) {
240
- adapter.log.error("time not long enough for " + id);
241
-
242
- }
243
- else if (!time.includes(":")) {
244
- adapter.log.error("time ':' missing for " + id);
245
- }
246
- else {
247
- const times = time.split(":");
248
- sRet = "0" + times[0].slice(-2) + ":" + "0" + times[1].slice(-2);
249
- }
250
-
251
- }
252
- catch (e) {
253
- adapter.log.error("exception in CheckValidTime [" + e + "] for " + id + " " + JSON.stringify(time));
254
-
255
- }
256
- return sRet;
257
-
258
- }
259
-
260
-
261
- function Check4ValidTemperature(adapter, temperature) {
262
-
263
- try {
264
-
265
- if (typeof temperature == "object") {
266
- adapter.log.warn("target temperature is object " + JSON.stringify(temperature));
267
- }
268
-
269
- if (isNaN(temperature) || typeof temperature === "string") {
270
-
271
- adapter.log.debug("try to convert " + temperature + " to a number");
272
- return Number(temperature);
273
- }
274
- else {
275
- return temperature;
276
- }
277
-
278
- }
279
- catch (e) {
280
- adapter.log.error("exception in Check4ValidTemperature [" + e + "]");
281
- return 0;
282
- }
283
-
284
- }
285
-
286
-
287
- function IsSummerTime(adapter, sStartDate, sEndDate) {
288
-
289
- let ret = false;
290
- try {
291
-
292
- adapter.log.debug("check in time " + sStartDate + " " + sEndDate);
293
-
294
- if (sStartDate.length > 0 && sEndDate.length > 0) {
295
- const StartPeriod = sStartDate.split(/[.,/ -]/);
296
- const EndPeriod = sEndDate.split(/[.,/ -]/);
297
-
298
- if (StartPeriod.length >= 2 && EndPeriod.length >= 2) {
299
-
300
- const StartDate = new Date();
301
- StartDate.setDate(parseInt(StartPeriod[0]));
302
- StartDate.setMonth(parseInt(StartPeriod[1]) - 1);
303
- adapter.log.debug("Start " + StartDate.toDateString());
304
-
305
- const EndDate = new Date();
306
- EndDate.setDate(parseInt(EndPeriod[0]));
307
- EndDate.setMonth(parseInt(EndPeriod[1]) - 1);
308
- adapter.log.debug("End " + EndDate.toDateString());
309
-
310
- const now = new Date();
311
-
312
- //bei Jahreswechsel
313
- if (EndDate < StartDate) {
314
- if (now > EndDate) {
315
- //end already past, increase end year
316
- EndDate.setFullYear(EndDate.getFullYear() + 1);
317
- adapter.log.debug("corrected End " + EndDate.toDateString());
318
- }
319
- else {
320
- //else decrease Start year
321
- StartDate.setFullYear(StartDate.getFullYear() - 1);
322
- adapter.log.debug("corrected Start " + StartDate.toDateString());
323
- }
324
- }
325
-
326
- if (now >= StartDate && now <= EndDate) {
327
- adapter.log.debug("we are in period");
328
- ret = true;
329
- }
330
- else {
331
- adapter.log.debug("we are not in period, after start " + StartDate.toDateString() + " and before end " + EndDate.toDateString());
332
- ret = false;
333
- }
334
- }
335
- }
336
- }
337
- catch (e) {
338
- adapter.log.error("exception catch in IsSummerTime [" + e + "] ");
339
- }
340
- return ret;
341
- }
342
-
343
-
344
-
345
- function GetTranslation(adapter,text, systemLang) {
346
-
347
- let translated = text;
348
-
349
- if (heatingcontrolDictionary[text]) {
350
- translated = heatingcontrolDictionary[text][systemLang] || heatingcontrolDictionary[text].en;
351
- }
352
-
353
-
354
- return translated;
355
- }
356
-
357
-
358
- module.exports = {
359
- IsLater,
360
- IsEarlier,
361
- IsEqual,
362
- findObjectsIdByKey,
363
- findObjectIdByKey,
364
- findObjectsByKey,
365
- findObjectByKey,
366
- timeConverter,
367
- CheckValidTime,
368
- Check4ValidTemperature,
369
- IsSummerTime,
370
- GetTranslation
371
- };