tobyweston / temperature-machine

Data logger for multiple DS18B20 temperature sensors on one or more machines
Apache License 2.0
67 stars 22 forks source link

Feature Request: Display Individual Temperatures #1

Closed damirj79 closed 7 years ago

damirj79 commented 7 years ago

Hello,

would it be possible to deal for custom development of few features:

  1. removing restriction of 5 sensors per board, 8 would be ideal
  2. instead of showing average temperature over all connected sensors, show current temperature for every connected sensor on the left side, organized vertically.

Everything else is more or less perfect, thank you for sharing the project with DIY.

Regards, Damir

tobyweston commented 7 years ago

I'll have a proper look as soon as I can and make some notes and we can take it from there. Thanks for posting 😄

tobyweston commented 7 years ago

Showing current temperature for each sensor in the UI

Averaging Measurements

The /temperature endpoint is the bit that does averaging. Changing TemperatureEndpoint.scala L17 to

   "measurements" := measurements.values

will send back a list of temperatures rather than a single average.

The UI should just deal with it (in theory) although you'll see multiple "hosts" shown; it's show each sensor labelled as "lounge", "garage" etc rather than "sensor-1" and "sensor-2".

The JSON will look like this

{
  "measurements" : [
    {
      "host" : "lounge",
      "seconds" : 100,
      "sensors" : [
        {
          "celsius" : 31.1
        },
        {
          "celsius" : 32.8
        }
      ]
    },
    {
      "host" : "bedroom",
      "seconds" : 200,
      "sensors" : [
        {
          "celsius" : 21.1
        },
        {
          "celsius" : 22.8
        }
      ]
    }
  ]
}

rather than this

  "measurements" : [
    {
      "host" : "lounge",
      "seconds" : 100,
      "sensors" : [
        {
          "celsius" : 31.95
        }
      ]
    },
    {
      "host" : "bedroom",
      "seconds" : 200,
      "sensors" : [
        {
          "celsius" : 21.950000000000003
        }
      ]
    }
  ]
}

So we'd need to modify the JSON to include the sensor name.

Sensor Names

The sensor names as stored in the RRD are based on the host name. For example, I name each Pi's hostname to reflect it's location, say lounge or study. Each sensor is postfixed with sensor-n where n is 1 to 5 (MaxSensors).

We could encode the same number in the JSON above, something like this.

{
  "measurements": [
    {
      "host": "lounge",
      "seconds": 100,
      "sensors": [
        {
          "name": "sensor-1",
          "celsius": 31.95
        }
      ]
    }
  ]
}

but it might be nicer to base it on perhaps a mapping to a user friendly name? or the actual sensor ID (ie 28-xxxxxxx)

So threading through a change in TemperatureReader from

trait TemperatureReader {
  def read: Error \/ List[Temperature]
}

to

trait TemperatureReader {
  def read: Error \/ List[(String, Temperature)]
}

and then in SensorReader, a change to reflect the filename

val toReading: SensorFile => Error \/ SensorTemperature = file => {
    for {
      source      <- fromTryCatchNonFatal(Source.fromFile(file)).leftMap(FileError)
      data        <- source.getLines().toList.headOption.toRightDisjunction(UnexpectedError("Problem reading file, is it empty?"))
      temperature <- Parser.parse(data)
    } yield (file.getName, temperature)
  }

We could then create JSON that look like this.

{
  "host": "localhost",
  "seconds": 1000,
  "sensors": [
    {
      "name": "28-000005e2fdc2",
      "temperature": {
        "celsius": 32.1
      }
    },
    {
      "name": "28-000005eef3a4",
      "temperature": {
        "celsius": 32.8
      }
    }
  ]
}
damirj79 commented 7 years ago

Tnx, i will try to perform changes over the weekend and hope it will be showing values as intended.

damirj79 commented 7 years ago

Looks like i did something wrong, I receive the errors below:

[info] + Bad json when writing sensor data [error] x Get multiple sensors, averaging the temperatures [error] '{ [error] "measurements" : [ [error] { [error] "host" : "lounge", [error] "seconds" : 100, [error] "sensors" : [ [error] { [error] "celsius" : 31.1 [error] }, [error] { [error] "celsius" : 32.8 [error] } [error] ] [error] }, [error] { [error] "host" : "bedroom", [error] "seconds" : 200, [error] "sensors" : [ [error] { [error] "celsius" : 21.1 [error] }, [error] { [error] "celsius" : 22.8 [error] } [error] ] [error] } [error] ] [error] }' [error] [error] is not equal to [error] [error] '{ [error] "measurements" : [ [error] { [error] "host" : "lounge", [error] "seconds" : 100, [error] "sensors" : [ [error] { [error] "celsius" : 31.95 [error] } [error] ] [error] }, [error] { [error] "host" : "bedroom", [error] "seconds" : 200, [error] "sensors" : [ [error] { [error] "celsius" : 21.950000000000003 [error] } [error] ] [error] } [error] ] [error] }' (TemperatureEndpointTest.scala:90) [error] Actual: { [error] ..." : [ [error] { [error] ...nge", [error] ... 100, [error] ..." : [ [error] ... { [error] ...: 31.[1] [error] ... }[,] [error] ... [ {] [error] [ "celsius" : 32.8] [error] [ }] [error] ... [] [error] [}], [error] [{] [error] ... ["host"] [:] ["bedroom",] [error] ... []"[s]e[cond]s"... 2[]00[,] [error] ... ["sensors"] [:] [] [error] ... [ {] [error] [ "celsius" : 21.1] [error] [ },] [error] [ {] [error] Expected: { [error] ..." : [ [error] { [error] ...nge", [error] ... 100, [error] ..." : [ [error] ... { [error] ...: 31.[95] [error] ... }[] [error] ... [] [error] [},] [error] [{] [error] ... ["host" : "bedroom",] [error] [ "seconds" : 200], [error] ...: [] [error] ... [] [] [{] [error] ... [ ]"[c]e[lsiu]s"... 2[1.95]00[00000000003] [error] ... [] [] [}] [error] ... [] [error] [}] [error] [] [error] [}] [info]

tobyweston commented 7 years ago

I'm working on a patch atm that may be what you want. In the mean time, if you want me to take a look at your error above, you can fork the repo and push.

damirj79 commented 7 years ago

Tnx

tobyweston commented 7 years ago

Renaming issue to 'Display Individual Temperatures', will track the 'More Sensors' requirements in #3

tobyweston commented 7 years ago

The above should give you back individual temperatures (from /temperatures) and averaged from /temperatures/average.

The temperatures.js and index.html still use the averaged values so the next step is to change the UI to show individual temperatures. It'd be nice if you could switch between the two and if we render the sensor name taken directly from the JSON.

A bit like this (showing average temperature).

screen shot 2017-02-03 at 19 26 02

or this, showing individual temperatures.

screen shot 2017-02-03 at 20 43 46
tobyweston commented 7 years ago

0b1cd6f will display the sensor name like the above screen shot but requires you to change the url of the ajax call to get individual temperatures rather than averages.

Change L4 of temperature.js to temperatures from temperatures/average and restart the server to experiment.

Let me know your thoughts and if you have any ideas how to toggle it in the UI.

I'm also interested how we can present it in a nice way when you have a lot of sensors attached. I think it'll look a bit rubbish if the current temperatures display as a long list on the left, taller than the chart. Perhaps display them horizontally?

damirj79 commented 7 years ago

Maybe you are right, in case there are x number of sensors, the vertical list can be very long and not nice to look at. In this case I agree that horizontal alignment is better looking.

Regarding the averaging function, maybe it would be good to put an option to enable it and then let the user to choose from which sensor to calculate average value and display it as an average value. The other unselected sensors are displayed individually.

tobyweston commented 7 years ago

Merged what we have so far (#4) into Master.

Spun up another project (https://github.com/tobyweston/temperature-machine-ui) to play with a more dynamic site. The JavaScript / static HTML site in this project are a bit... 💩. The new site will let you toggle average and individual temperatures.

tobyweston commented 7 years ago

FYI This is what I'm thinking / have spiked over on the UI project. Comments welcome.

toggle

tobyweston commented 7 years ago

Marking as fixed (ccd8dd1), the new UI can switch between all sensors and averaged as above. It also updates the temperatures automatically.

tobyweston commented 7 years ago

Had some failing tests, if you're having problems with sbt assembly or sbt test, update and try again. There may be some platform specific problems with Windows however...

@damirj79 let me if it fixes your problem

damirj79 commented 7 years ago

Hi,

the assembly is now OK and also the service starts up correctly as it is visible in temperature-machine.log file, web page also loads, but all temperature gadgets shows Error: Network Error and image graphs for 24 hours, 7 days and 1 month shows message "image unavailble".

tobyweston commented 7 years ago

@damirj79 I may have been a bit eager. I'll check but it might be a port configuration thing. If youre running Chrome can you open the developer tools and see which the end points are being called for *.png etc. I'll have a look myself and report back...

damirj79 commented 7 years ago

It looks like the gadgets and graphs are pointing to http://localhost:11900 instead of https://hostname:11900 or http://IPaddress:11900

GET http://localhost:11900/temperature-1-days.png net::ERR_CONNECTION_REFUSED localhost:11900/temperature-7-days.png:1 GET http://localhost:11900/temperature-7-days.png net::ERR_CONNECTION_REFUSED localhost:11900/temperature-30-days.png:1 GET http://localhost:11900/temperature-30-days.png net::ERR_CONNECTION_REFUSED xhr.js:175 GET http://localhost:11900/temperature.json net::ERR_CONNECTION_REFUSED (anonymous) @ xhr.js:175 e.exports @ xhr.js:12 e.exports @ dispatchRequest.js:52 xhr.js:175 GET http://localhost:11900/temperatures/average net::ERR_CONNECTION_REFUSED (anonymous) @ xhr.js:175 e.exports @ xhr.js:12 e.exports @ dispatchRequest.js:52 xhr.js:175 GET http://localhost:11900/temperatures/average net::ERR_CONNECTION_REFUSED

If I change http://localhost:11900/temperature-1-days.png to http://raspberrypi:11900/temperature-1-days.png the graph shows up correctly.

tobyweston commented 7 years ago

yup, makes sense, thanks. I hardcoded the hostname (full qualifying) it to test. I need to switch it to a relative URL. Will fix up and report back...

@damirj79 ok, should be fixed (no promises!) try that it you like (93ef93a) 👍

damirj79 commented 7 years ago

Looks good indeed, thanks. 👍 Just one question though, Last 24 hours graph is showing 12hour format. Is there a simple way to convert it to 24 hour format?

tobyweston commented 7 years ago

Good stuff. I'll have a look, it's chartjs format so I'm sure they support 24h format. I'm going to tweak it a bit anyway with tool tips etc

tobyweston commented 7 years ago

Should be in 24h format now