It's a Sun 'O' Clock

In the UK our timezone presents huge differences of daylight between Winter and Summer, so I thought I would knockup a quick Realtime Sun Clock to quickly show time dawn, daylight dusk and nighttime.
This became a very simple task using Node-Red / Canvas Gauge Card and Home Assistant and I just thought it might be useful to others to show how you can incorporate the Custom card-templater to do this.
In Node-Red I used the Bigtimer to grab the Dawn/Sunrise/Dusk/Sunset times.
Using that node is so simple as it presents the data in minutes and then this is easily converted to decimal hrs. (there are loads of ways to get this data even without Node-red).

Using the Canvas Gauge Card you can create beautiful looking dials and I used this in conjunction with the Custom Card-templater to get the dial to show the current dawn/daylight/dusk and nighttime as the data highilghts

Here is the canvas gauge card data

type: custom:card-templater
entities:
  - sensor.sunstart
  - sensor.sunend
  - sensor.nowhrs
card:
  type: custom:canvas-gauge-card
  entity: sensor.nowhrs
  attribute: azimuth
  card_height: 300
  gauge:
    animation: false
    animationTarget: needle
    type: radial-gauge
    needleType: arrow
    needleWidth: 3
    colorNeedle: rgb(77, 84, 92, .90)
    colorNeedleEnd: rgb(150, 161, 176, 90)
    needleShadow: true
    colorNeedleShadowUp: rgba(209, 223, 240,.90)
    colorNeedleShadowDown: rgba(77, 84, 92, .10)
    colorNeedleCircleOuterEnd: rgba(102, 100, 34, .90)
    colorNeedleCircleOuter: rgba(81, 129, 138, .10)
    colorNeedleCircleInner: rgba(248, 250, 187, .99)
    colorNeedleCircleInnerEnd: rgba(81, 129, 138, .99)
    colorPlateEnd: rgba(179, 179, 30, .50)
    colorPlate: rgba(255, 255, 245, .90)
    title: Sun 'O' Clock
    width: 300
    height: 300
    borderShadowWidth: 1
    borderOuterWidth: 1
    borderMiddleWidth: 8
    borderInnerWidth: 10
    colorBorderMiddle: rgba(237, 242, 99, .10)
    colorBorderMiddleEnd: rgba(183, 189, 21, .99)
    colorBorderInnerEnd: rgba(183, 189, 21, .99)
    colorBorderInner: rgba(237, 242, 99, .10)
    minValue: 0
    maxValue: 24
    startAngle: 0
    ticksAngle: 360
    valueBox: false
    majorTicks:
      - 0
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
      - 10
      - 11
      - 12
      - 13
      - 14
      - 15
      - 16
      - 17
      - 18
      - 19
      - 20
      - 21
      - 22
      - 23
      - 24
    fontTitleWeight: bolder
    colorValueBoxBackground: rgb(245, 240, 240)
    colorValueBoxRectEnd: rgb(176,172,172)
    colorValueBoxRect: rgb(176,172,172)
    valueInt: 1
    valueDec: 0
    valueBoxBorderRadius: 10
    valueBoxStroke: 1
    valueBoxWidth: 40
    minorTicks: 10
    strokeTicks: true
    useMinPath: false
    highlights:
      - from_template: '{{ state_attr("sensor.sunstart", "dawn")}}'
        to_template: '{{ states("sensor.sunstart")}}'
        color: rgba(3, 15, 252, .20)
      - from_template: '{{ states("sensor.sunend")}}'
        to_template: '{{ state_attr("sensor.sunend", "dusk")}}'
        color: rgba(3, 15, 252, .20)
      - from_template: '{{ state_attr("sensor.sunend", "dusk")}}'
        to_template: '{{ state_attr("sensor.sunstart", "dawn")}}'
        color: rgba(3, 15, 252, .70)
      - from_template: '{{ states("sensor.sunstart")}}'
        to_template: '{{ states("sensor.sunend")}}'
        color: rgba(245, 202, 7, .60)

SunClock

Enjoy …

7 Likes

Lol I was just looking for this to say that they would look good together

But if course that’s yours too!

Ahha! you spotted the similarity. I have these dials all over the place
sumazi
sunele

Post Removed!

Hmm…this is cool, but I’m stuck on what the state calculation should be for sensor.nowhrs.

In NodeRED, I’ve passed the bigtimer output to a sensor node, using msg.now as the state for sensor.nowhrs. I don’t think that’s correct.

My gauge is ticking every minute to the hour mark…

What should the state for sensor.nowhrs represent?

I am using the SUN Position Node to get the data for the sun, I dumped the BigTimer for this use as there were some complications with the data it provided.
Here is my Node-Red Function, which also gives me the details for a different location, which you can remove. Hope that helps

[{"id":"4b905fc0492c05cd","type":"function","z":"9d291d29511e50cd","g":"1a69ba6456f1be21","name":"function 67","func":"\nvar dawn = (msg.payload.times.dawn.ts);\nvar sunrise = (msg.payload.times.sunrise.ts);\nvar dusk = (msg.payload.times.dusk.ts);\nvar sunset = (msg.payload.times.sunset.ts);\nvar now = msg.payload.ts;\n\n//MEDELLIN -6hrs\nif (msg.payload.longitude == -75.5936257){\n   var moffset = (6*3600*1000);\n   dawn = dawn - moffset;\n   sunrise = sunrise - moffset;\n   dusk = dusk - moffset;\n   sunset = sunset - moffset;\n   now = now - moffset;\n}\n\nif (msg.payload.longitude == -3.7729661){\n   var moffset = 0;\n   dawn = dawn - moffset;\n   sunrise = sunrise - moffset;\n   dusk = dusk - moffset;\n   sunset = sunset - moffset;\n   now = now - moffset;\n\n}\n    msg.payload = {\n        \n        dawn: new Date(dawn).getHours() + (new Date(dawn).getMinutes()/60),\n        sunrise: new Date(sunrise).getHours() + (new Date(sunrise).getMinutes() / 60),\n        dusk: new Date(dusk).getHours() + (new Date(dusk).getMinutes() / 60),\n        sunset: new Date(sunset).getHours() + (new Date(sunset).getMinutes() / 60),\n        now: new Date(now).getHours() + (new Date(now).getMinutes() / 60)  \n\n    }\n\nreturn msg;        ","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":1060,"wires":[["833b20d40b942c61"]]}]

Hello @Lordlinhey

Can you please post the code for the azimuth gauge

I can’t get it to work that the space between the numbers is correct —> picture

I set the numbers like yours

Thank you so much

Ah you have to do the little trick of using ‘exactTicks: true’.

Anyway here is my code.
Note: I have turned the whole thing upside down now so that the 0 faces North, it just makes it easier to spot where the sun should be on the miserable summer days we are experiencing.

type: custom:canvas-gauge-card
entity: sensor.k_sun_azimuth
card_height: 250
gauge:
  type: radial-gauge
  title: Azimuth
  width: 250
  height: 250
  borderShadowWidth: 1
  borderOuterWidth: 1
  borderMiddleWidth: 8
  borderInnerWidth: 10
  colorBorderMiddle: rgba(237, 242, 99, .10)
  colorBorderMiddleEnd: rgba(183, 189, 21, .99)
  colorBorderInnerEnd: rgba(183, 189, 21, .99)
  colorBorderInner: rgba(237, 242, 99, .10)
  colorPlateEnd: rgba(179, 179, 30, .50)
  colorPlate: rgba(255, 255, 245, .10)
  exactTicks: true
  minValue: 40
  maxValue: 320
  startAngle: 220
  ticksAngle: 280
  valueBox: false
  majorTicks:
    - 50
    - 60
    - 90
    - 120
    - 150
    - 180
    - 210
    - 240
    - 270
    - 300
    - 310
    - 0
  fontTitleWeight: bolder
  colorValueBoxBackground: rgb(245, 240, 240)
  colorValueBoxRectEnd: rgb(176,172,172)
  colorValueBoxRect: rgb(176,172,172)
  valueInt: 2
  valueDec: 0
  valueBoxBorderRadius: 10
  valueBoxStroke: 1
  valueBoxWidth: 25
  minorTicks: 3
  strokeTicks: true
  borders: false
  highlights:
    - from: 50
      to: 88
      color: rgba(201, 166, 6, .60)
    - from: 88
      to: 127
      color: rgba(245, 202, 7, .30)
    - from: 232
      to: 271
      color: rgba(3, 15, 252, .30)
    - from: 271
      to: 310
      color: rgba(3, 15, 252, .60)

@Lordlinhey

Can you also please post the code for the elevation gauge?

Thanks

Aaaaah this is what I’m searching for
Thank you so much

Also very nice with “0” UP

1 Like

Here is the code for my elevation gauge

type: custom:canvas-gauge-card
entity: sensor.k_sun_elevation
card_height: 300
gauge:
  type: radial-gauge
  title: Elevation
  width: 300
  height: 300
  borderShadowWidth: 1
  borderOuterWidth: 1
  borderMiddleWidth: 8
  borderInnerWidth: 10
  colorBorderMiddle: rgba(237, 242, 99, .10)
  colorBorderMiddleEnd: rgba(183, 189, 21, .99)
  colorBorderInnerEnd: rgba(183, 189, 21, .99)
  colorBorderInner: rgba(237, 242, 99, .10)
  colorPlateEnd: rgba(179, 179, 30, .50)
  colorPlate: rgba(255, 255, 245, .10)
  minValue: -90
  maxValue: 90
  startAngle: 0
  ticksAngle: 180
  valueBox: true
  majorTicks:
    - '-90'
    - '-75'
    - '-60'
    - '-45'
    - '-30'
    - '-15'
    - '0'
    - '15'
    - '30'
    - '45'
    - '60'
    - '75'
    - '90'
  fontTitleWeight: bolder
  colorValueBoxBackground: rgb(245, 240, 240)
  colorValueBoxRectEnd: rgb(176,172,172)
  colorValueBoxRect: rgb(176,172,172)
  valueInt: 0
  valueDec: 0
  valueBoxBorderRadius: 10
  valueBoxStroke: 1
  valueBoxWidth: 20
  minorTicks: 3
  strokeTicks: true
  borders: false
  highlights:
    - from: 60
      to: 90
      color: rgba(142, 245, 7, .50)
    - from: -90
      to: 0
      color: rgba(109, 149, 156, .50)

1 Like

Here is another of my gauges, which I use for LUX in case anyone is interested.

image

type: custom:canvas-gauge-card
entity: sensor.hall_down_sensor_illuminance
card_height: 300
gauge:
  title: LX DN
  width: 300
  height: 300
  animation: true
  barShadow: 5
  colorBarProgress: rgba(50,200,50,.75)
  barWidth: 10
  animationTarget: needle
  type: radial-gauge
  needleType: arrow
  needleWidth: 3
  colorNeedle: rgb(237, 242, 99)
  colorNeedleEnd: rgb(247, 255, 15)
  needleShadow: true
  colorNeedleShadowUp: rgba(52, 145, 199,.50)
  colorNeedleShadowDown: rgba(81, 129, 138, .10)
  colorNeedleCircleOuterEnd: rgba(102, 100, 34, .90)
  colorNeedleCircleOuter: rgba(81, 129, 138, .10)
  colorNeedleCircleInner: rgba(248, 250, 187, .99)
  colorNeedleCircleInnerEnd: rgba(81, 129, 138, .99)
  colorPlateEnd: rgba(179, 179, 30, .50)
  colorPlate: rgba(255, 255, 245, .10)
  borderShadowWidth: 1
  borderOuterWidth: 1
  borderMiddleWidth: 8
  borderInnerWidth: 10
  colorBorderMiddle: rgba(237, 242, 99, .10)
  colorBorderMiddleEnd: rgba(183, 189, 21, .99)
  colorBorderInnerEnd: rgba(183, 189, 21, .99)
  colorBorderInner: rgba(237, 242, 99, .10)
  minValue: 0
  maxValue: 110
  startAngle: 45
  ticksAngle: 270
  valueBox: true
  exactTicks: true
  majorTicks:
    - 0
    - 10
    - 20
    - 30
    - 40
    - 50
    - 60
    - 70
    - 80
    - 90
    - 100
  fontTitleWeight: bolder
  colorValueBoxBackground: rgb(245, 240, 240)
  colorValueBoxRectEnd: rgb(176,172,172)
  colorValueBoxRect: rgb(176,172,172)
  valueInt: 1
  valueDec: 0
  valueBoxBorderRadius: 10
  valueBoxStroke: 1
  valueBoxWidth: 40
  minorTicks: 2
  strokeTicks: true
  useMinPath: false
  highlights:
    - from: 0
      to: 10
      color: rgba(13, 13, 13, .60)
    - from: 10
      to: 20
      color: rgba(13, 13, 13, .40)
    - from: 20
      to: 30
      color: rgba(13, 13, 13, .30)
    - from: 30
      to: 50
      color: rgba(13, 13, 13, .20)
    - from: 50
      to: 90
      color: rgba(13, 13, 13, .10)
    - from: 90
      to: 110
      color: rgba(13, 13, 13, .05)
    - from: 110
      to: 125
      color: rgba(13, 13, 13, .00)
1 Like

@Lordlinhey

Thank you, I appreciate this.