frugal-iot-client 1.3.11 → 1.3.12

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.
@@ -22,7 +22,10 @@
22
22
  "Bash(curl *)",
23
23
  "Bash(grep -n \"el\\('p', {}, \\\\[\\\\\"\" webcomponents.js)",
24
24
  "Bash(grep -n \"el\\('h[1-5]', {}, \\\\[\\\\\"\" webcomponents.js)",
25
- "Bash(grep -n \"^const languages\\\\|^EN:\\\\|^FR:\\\\|^HI:\\\\|^ID:\\\\|^\\\\`\\);\" /Users/mitra/git/github_mitra42/frugal-iot-client/webcomponents.js)"
25
+ "Bash(grep -n \"^const languages\\\\|^EN:\\\\|^FR:\\\\|^HI:\\\\|^ID:\\\\|^\\\\`\\);\" /Users/mitra/git/github_mitra42/frugal-iot-client/webcomponents.js)",
26
+ "WebFetch(domain:raw.githubusercontent.com)",
27
+ "Read(//Users/mitra/git/github_mitra42/**)",
28
+ "Read(//Users/mitra/git/github_mitra42/frugal-iot-server/**)"
26
29
  ]
27
30
  }
28
31
  }
package/package.json CHANGED
@@ -30,5 +30,5 @@
30
30
  "test": "echo \"Error: no test specified\" && exit 1"
31
31
  },
32
32
  "type": "module",
33
- "version": "1.3.11"
33
+ "version": "1.3.12"
34
34
  }
package/webcomponents.js CHANGED
@@ -1541,20 +1541,38 @@ class MqttTopic {
1541
1541
  }
1542
1542
  })
1543
1543
  .then(csvData => {
1544
+ // The server appends to these files as readings arrive, so one can end mid-line if the
1545
+ // power was cut while it was being written - a truncated number, a missing column, or an
1546
+ // opening quote with nothing after it. These options make the parser drop whatever is
1547
+ // damaged and return the rest, instead of rejecting the whole file, which would lose a
1548
+ // day of readings over one bad byte at the end.
1544
1549
  // noinspection JSCheckFunctionSignatures
1545
- parse(csvData, (err, newdata) => {
1550
+ parse(csvData, {relax_quotes: true, relax_column_count: true, skip_records_with_error: true}, (err, newdata) => {
1546
1551
  if (err) {
1547
- console.error(err); // Intentionally not passing error back
1548
- } else if (newdata.length === 0) {
1549
- XXX(["No data in", filepath]);
1552
+ console.error("Could not read", filepath, err.message);
1553
+ this.markNoDataForDay();
1554
+ cb(null); // Not an error to the caller - one unreadable day should not stop the rest
1550
1555
  } else {
1551
- console.log(`retrieved ${newdata.length} records for ${this.topicPath}`);
1552
- let newprocdata = newdata.map(r => {
1553
- return {
1554
- time: parseInt(r[0]),
1555
- value: this.valueFromText(r[1]) // TODO-72 need function for this as presuming its float
1556
- };
1557
- });
1556
+ // A record can survive the parse but still be unusable - a torn last line often leaves
1557
+ // just a timestamp, or half of one
1558
+ let newprocdata = newdata
1559
+ .filter(r => (r.length >= 2) && !isNaN(parseInt(r[0])))
1560
+ .map(r => {
1561
+ return {
1562
+ time: parseInt(r[0]),
1563
+ value: this.valueFromText(r[1]) // TODO-72 need function for this as presuming its float
1564
+ };
1565
+ });
1566
+ if (newdata.length !== newprocdata.length) {
1567
+ console.warn(`ignored ${newdata.length - newprocdata.length} damaged record(s) in ${filepath}`);
1568
+ }
1569
+ if (newprocdata.length === 0) {
1570
+ XXX(["No data in", filepath]);
1571
+ this.markNoDataForDay();
1572
+ cb(null); // Nothing to add, but the caller still has to be told this one is finished
1573
+ return;
1574
+ }
1575
+ console.log(`retrieved ${newprocdata.length} records for ${this.topicPath}`);
1558
1576
  let olddata = this.data.splice(0, Infinity);
1559
1577
  for (let dd of newprocdata) {
1560
1578
  this.data.push(dd);
@@ -1576,18 +1594,25 @@ class MqttTopic {
1576
1594
  })
1577
1595
  .catch(ignored => {
1578
1596
  // Did not get any data, draw dotted line from beginning of day to now (and end of prev data to start this day)
1579
- let t = new Date(this.graph.state.dateFrom) // Have to explicitly copy it else pointer
1580
- .setUTCHours(0,0,0,0)
1581
- .valueOf();
1582
- this.data.splice(0, 0, {
1583
- time: t,
1584
- value: null,
1585
- });
1597
+ this.markNoDataForDay();
1586
1598
  //console.error(err); - dont need error - the fetch will also report it, so it is just a repeat.
1587
1599
  cb(null); // Dont break caller
1588
1600
  }); // May want to report filename here
1589
1601
  }
1590
1602
 
1603
+ // Nothing usable for this day, whether the file was missing, empty or damaged. A null point at
1604
+ // the start of the day makes the graph draw a dotted line across the gap rather than joining the
1605
+ // days either side as though nothing were missing.
1606
+ markNoDataForDay() {
1607
+ let t = new Date(this.graph.state.dateFrom) // Have to explicitly copy it else pointer
1608
+ .setUTCHours(0,0,0,0)
1609
+ .valueOf();
1610
+ this.data.splice(0, 0, {
1611
+ time: t,
1612
+ value: null,
1613
+ });
1614
+ }
1615
+
1591
1616
  removeDataBefore(date) { // note date may be null
1592
1617
  let i;
1593
1618
  if (date) {