Skip to content

Commit b9efd43

Browse files
committed
#93 #48 looks like new installs from scratch work correctly now
1 parent 5246f14 commit b9efd43

13 files changed

+110
-17
lines changed

balena.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: "BubblesNet Controller"
22
type: "sw.application"
33
description: >-
4-
Deep-water-culture hydroponics ... automated
4+
Deep-water-culture (DWC) hydroponics ... automated
55
post-provisioning: >-
66
77
## Introduction
@@ -12,6 +12,8 @@ post-provisioning: >-
1212
1313
- Requires at least 4G RAM, preferably 8G. Developed and tested on 8G, known not to work on 1G. RAM requirement driven almost entirely by ActiveMQ.
1414
15+
- Bring a sandwich to this process. After you flash a micro-SD card and start it up, it can take 20+ minutes for the device to connect and update via Balena.
16+
1517
- This is literally an alpha-release. The underlying code has been in production for months, but the deployment to a Balena public fleet is brand new and has required a number of modifications.
1618
1719

client/src/AuthenticatedApp.js

+16
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,14 @@ function AuthenticatedApp (props) {
199199
const [switch_state, setSwitchState] = useState(props.initial_switch_state);
200200
const [sensor_readings] = useState(initial_sensor_readings);
201201
const [tilt,setTilt] = useState({ currently_tilted: false, last_tilt: 0} )
202+
/* let initial_lastseen = []
203+
for( let i = 0; i < site.stations[currentStationIndex].attached_devices.length; i++ ) {
204+
initial_lastseen.push({deviceid: site.stations[currentStationIndex].attached_devices[i].deviceid,
205+
lastseen_millis: site.stations[currentStationIndex].attached_devices[i].lastseen_millis})
206+
}
207+
console.log("initial_lastseen = " + JSON.stringify(initial_lastseen))
208+
const [lastseen, setLastseen] = useState(initial_lastseen)
209+
*/
202210

203211
/**
204212
* Port the API server is listening on - change it and rerender
@@ -386,6 +394,14 @@ function AuthenticatedApp (props) {
386394
sensor_readings[msg.measurement_name + "_direction"] = msg.direction
387395
sensor_readings[msg.measurement_name + "_units"] = msg.units
388396
log.trace("msg: applying " + msg.value + " " + sensor_readings[msg.measurement_name + "_direction"] + " to " + msg.measurement_name)
397+
/* for( let i = 0; i < lastseen.length; i++ ) {
398+
if( lastseen[i].deviceid == msg.deviceid ) {
399+
let new_lastseen = JSON.parse(JSON.stringify(lastseen))
400+
setLastseen( new_lastseen )
401+
break;
402+
}
403+
}
404+
*/
389405
}
390406
}
391407

client/src/components/CameraTab/CameraTabFunctional.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,14 @@ function RenderCameraTab(props) {
6868

6969

7070
function getDeviceRow(indexObject) {
71+
let displayed_lastpicture = moment(props.station.attached_devices[indexObject.device_index].latest_picture_datetimemillis).format("LLLL")
72+
if( displayed_lastpicture === 'Invalid date') {
73+
displayed_lastpicture = 'No Pictures Yet'
74+
}
7175

7276
// log.info("getDeviceRow " + JSON.stringify(indexObject) + ' label '+props.station.attached_devices[indexObject.device_index] + ' areas ' + JSON.stringify(Areas));
7377
return( <><Text gridArea={"label"+indexObject.labelarea_index}>{props.station.attached_devices[indexObject.device_index].deviceid + ' ' +
74-
moment(props.station.attached_devices[indexObject.device_index].latest_picture_datetimemillis).format("LLLL")}</Text>
78+
displayed_lastpicture }</Text>
7579
<Box gridArea={Areas[indexObject.picturearea_index].name}>
7680
<ReactImageZoom {...ImageProps[indexObject.imageprops_index]} />
7781
</Box></>);

client/src/components/DeviceMapTab/DeviceMapTabFunctional.js

+34-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
} from 'grommet'
3535
import RenderFormActions from "../FormActions";
3636
import GoogleFontLoader from "react-google-font-loader";
37+
import moment from "moment";
3738

3839
import {getContainerNames, getModuleTypes} from '../../api/utils';
3940
import log from "roarr";
@@ -68,10 +69,10 @@ function RenderDeviceMapTab (props) {
6869
let [displaySettings] = useState({units: 'IMPERIAL', language: 'en-us', languageOptions:['en-us','fr'], theme: props.theme}); //
6970

7071
function getAddress( module ) {
71-
if( module.device_type === "GPIO" ) {
72-
return ""
72+
if (module.protocol === "i2c") {
73+
return "i2c " + module.address + " "
7374
} else {
74-
return module.address + " "
75+
return module.protocol
7576
}
7677
}
7778

@@ -109,6 +110,25 @@ function RenderDeviceMapTab (props) {
109110
return ret
110111
}
111112

113+
function getDevices() {
114+
// console.log("getModules " + JSON.stringify(station))
115+
// log.trace("arr = " + JSON.stringify(arr))
116+
let ret = station.attached_devices.map(getDeviceRow)
117+
return ret
118+
}
119+
120+
function getDeviceRow( row, index, arr ) {
121+
console.log("row.lastseen_millis = "+row.lastseen_millis)
122+
let displayed_lastseen = moment(row.lastseen_millis).format("DD MMM YYYY hh:mm a")
123+
if( displayed_lastseen === 'Invalid date') {
124+
displayed_lastseen = 'never'
125+
}
126+
return <TableRow key={row.deviceid}>
127+
<TableCell >{row.deviceid}</TableCell>
128+
<TableCell >{displayed_lastseen}</TableCell>
129+
</TableRow>
130+
}
131+
112132
// function getTypeSelector(module) {
113133
// return <Text >{module.module_type} {module.module_name}</Text>
114134
// }
@@ -128,6 +148,7 @@ function RenderDeviceMapTab (props) {
128148
}
129149

130150
let module_rows = getModules()
151+
let devices = getDevices()
131152
// console.log("rendering with font set to " + values.theme.global.font.family)
132153
// console.log("station = " + JSON.stringify(station))
133154
let ret =
@@ -140,7 +161,16 @@ function RenderDeviceMapTab (props) {
140161
]}
141162
/>
142163
<div className="global_container_">
143-
<Table id="settings-tab" >
164+
<Table id="devicemap-lastseen-table" caption={"Edge devices and when they last messaged us."}>
165+
<tbody>
166+
<TableRow>
167+
<th >Device</th>
168+
<th >Last seen</th>
169+
</TableRow>
170+
{devices}
171+
</tbody></Table>
172+
<hr />
173+
<Table id="devicemap-modules-table" caption={"The sensor modules and which device they're attached to."}>
144174
<tbody>
145175
<TableRow>
146176
<th >Device</th>

client/src/components/DeviceMapTab/deviceMapTab.css

+23
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,26 @@
5656
#advanced-table {
5757
}
5858

59+
#devicemap-lastseen-table {
60+
margin-top: 30px;
61+
width: 800px;
62+
font-size: medium;
63+
border-collapse: collapse;
64+
}
65+
66+
#devicemap-lastseen-table td {
67+
border: 1px solid black; border-collapse: collapse;
68+
text-align: center;
69+
}
70+
71+
#devicemap-modules-table {
72+
margin-top: 30px;
73+
width: 800px;
74+
font-size: medium;
75+
}
76+
77+
#devicemap-modules-table td {
78+
border: 1px solid black; border-collapse: collapse;
79+
}
80+
81+

push_local.cmd

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
copy client\.env.production client\.env
2+
balena push --multi-dockerignore 192.168.23.163
3+
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE device DROP COLUMN lastseen_millis;

server/migrations/00000041_bu.up.sql

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE device ADD COLUMN lastseen_millis bigint NULL;

server/src/api/models/device.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2222
*/
2323
const log = require("../../bubbles_logger").log
24+
const moment = require('moment');
2425

2526
const locals = require("../../config/locals");
2627
const bcrypt = require('bcryptjs');
@@ -218,21 +219,28 @@ async function deleteDevice(deviceid) {
218219
})
219220
}
220221

221-
async function setJustSeenFromEvent(event) {
222-
return( await setJustSeen(event.deviceid))
222+
async function setJustSeenFromMessage(message) {
223+
return( await setJustSeen(message.deviceid))
223224
}
224225

225226
async function setJustSeen(deviceid) {
226227
return new Promise(function(resolve, reject) {
227-
log.info("setJustSeen "+JSON.stringify(deviceid))
228228

229-
pool.query("UPDATE device SET lastseen=NOW() where deviceid=$1 RETURNING *",
230-
[deviceid], (error, results) => {
229+
230+
let ms = moment().valueOf();
231+
232+
log.info("setJustSeen UPDATE device SET lastseen=NOW(), lastseen_millis="+ms+ " where deviceid="+deviceid)
233+
234+
pool.query("UPDATE device SET lastseen=NOW(), lastseen_millis=$2 where deviceid=$1 RETURNING *",
235+
[deviceid, ms], (error, results) => {
231236
if (error) {
232-
reject(error)
237+
let ret = {message: "setJustSeen failed for deviceid " + deviceid, deviceid: deviceid, error: error}
238+
log.error(JSON.stringify(ret))
239+
reject(ret)
233240
} else {
234-
// log.info("new event " + results.rows[0])
235-
resolve({rowCount: results.rowCount, message: "updated "+ results.rowCount+" rows lastseen for deviceid " + deviceid})
241+
let ret = {rowCount: results.rowCount, message: "updated "+ results.rowCount+" rows lastseen for deviceid " + deviceid}
242+
// log.info("setJustSeen returning " + JSON.stringify(ret))
243+
resolve(ret)
236244
}
237245
})
238246
});
@@ -249,7 +257,7 @@ module.exports = {
249257
getDevicesByStationId,
250258
createDefaultDevices,
251259
setJustSeen: setJustSeen,
252-
setJustSeenFromEvent: setJustSeenFromEvent,
260+
setJustSeenFromMessage: setJustSeenFromMessage,
253261
setLatestPicture,
254262
getDeviceShallow,
255263
}

server/src/api/models/module.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ async function createDefaultSetOfModules( body ) {
191191
async function getAllModulesByCabinet(stationid) {
192192
log.info("getAllModulesByCabinet " + stationid)
193193
return new Promise( function (resolve, reject) {
194-
let ssql = "select i2caddress, container_name, devicetypename, module_type, deviceid, moduleid, protocol from station c join device d on d.stationid_Station = stationid join devicetype t on d.devicetypeid_devicetype=t.devicetypeid join module m on m.deviceid_device = d.deviceid where c.stationid =$1"
194+
let ssql = "select lastseen, d.lastseen_millis, i2caddress, container_name, devicetypename, module_type, deviceid, moduleid, protocol from station c join device d on d.stationid_Station = stationid join devicetype t on d.devicetypeid_devicetype=t.devicetypeid join module m on m.deviceid_device = d.deviceid where c.stationid =$1"
195195
pool.query(ssql, [stationid], async (error, results) => {
196196
if (error) {
197197
log.info("getAllModulesByCabinet error " + error)

server/src/api/models/site.js

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ async function getSiteById(siteid) {
7171
FROM (
7272
SELECT c.stationid AS stationid,
7373
d.deviceid AS deviceid,
74+
d.lastseen,
75+
d.lastseen_millis,
7476
d.picamera,
7577
d.picamera_resolutionx,
7678
d.picamera_resolutiony,

server/src/api/models/station.js

+2
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ async function getStationConfigsBySite(siteid) {
112112
FROM (
113113
SELECT c.stationid AS stationid,
114114
d.deviceid AS deviceid,
115+
d.lastseen,
116+
d.lastseen_millis,
115117
d.picamera,
116118
d.picamera_resolutionx,
117119
d.picamera_resolutiony,

server/src/queue-server.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const message_type = require('./types').message_type
2626
const event = require('./api/models/event')
2727
const device = require('./api/models/device')
2828
const debug = require('debug')('queue-server')
29+
const moment = require('moment')
2930

3031
const bubbles_queue = require('./api/models/bubbles_queue')
3132
const outlet = require('./api/models/outlet')
@@ -115,7 +116,7 @@ async function storeMessage(body) {
115116

116117
// Set that this device was last seen just now. This may be too costly to do as
117118
// a database update
118-
let justseen_result = device.setJustSeenFromEvent(ev)
119+
let justseen_result = await device.setJustSeenFromMessage(message)
119120
log.info("justseen returns " + JSON.stringify(justseen_result))
120121
} catch( err ) {
121122
log.error("storeMessage error saving message " + err + " " + message)

0 commit comments

Comments
 (0)