Skip to content
This repository was archived by the owner on Sep 15, 2024. It is now read-only.

Commit a129d64

Browse files
authored
Feature/co2 sensor (#74)
* add co2-sensor app * change warn color * only show co2 app on value is on alarm level * check co2 value is unavailable or too old * add environment variables for CO2 sensor * add description of CO2 sensor environment values * change text * change alert text * rename env var APP_CO2_SENSOR_BASE_API_URL to HA_BASE_API_URL; move HA serverice outside the co2 sensor app * refactoring; use BME280 temperature for City-Weather * rename APP_CO2_SENSOR_ACCESS_TOKEN to HA_ACCESS_TOKEN; remove export for loadState() * fix convert temperature to number * load temperature also on init() * move co2 sensor app direct to the app folder * render humidity in progress bar * fix null checks; optimize code * remove service from file name * fix import * optimize code * fix city-weather app not shown because always hang in loading state * optimize config * fix always unready because is in loading state * refactoring; load OpenWeather data via Home Assistant service * update some libraries * update Axios library * fix NaN output; optimize code * upgrade to NodeJS 18 * move sonsors for HA weather app to environment variables; refactoring * fix content * fix check OWM is configured * fix check OWM was configured * fix ignore .env file
1 parent 6756814 commit a129d64

16 files changed

+349
-71
lines changed

.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
node_modules
22
npm-debug.log
3-
.evn
3+
.env
44
dist/

.env

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ SECONDARY_COLOR=#4CFF00
1010
APP_CITY_WEATHER_CITY_ID=your-city-id
1111
APP_CITY_WEATHER_APP_ID=your-app-id
1212
APP_CITY_WEATHER_UNITS=metric
13-
APP_CITY_WEATHER_MAX_CACHE_AGE=30
13+
APP_CITY_WEATHER_MAX_CACHE_AGE=30
14+
15+
HA_BASE_API_URL=http://my-server.com/home-assistant/api
16+
HA_ACCESS_TOKEN=your-access-token
17+
18+
APP_CO2_SENSOR_ENTITY_ID=sensor.co2meter_value
19+
APP_CO2_SENSOR_ALARM_THRESHOLD=1200

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:16-slim
1+
FROM node:18-slim
22

33
WORKDIR /usr/src/app
44

README.md

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,24 @@ Second: We think many users use AWTRIX servers on a raspberry pi with limitited
7171

7272
Overwrite following environment variables to setup your container:
7373

74-
| Name | Description |
75-
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
76-
| MQTT_SERVER | Adress of the MQTT broker in format "mqtt://192.168.1.1:1883" |
77-
| MQTT_USERNAME | Username to access the MQTT Broker |
78-
| MQTT_PASSWORD | Password of the MQTT user |
79-
| APP_ITERATIONS | Number of seconds before switching to the next app |
80-
| LOCALE | Country code for loading date time settings (e.g. "de") |
81-
| PRIMARY_COLOR | Color used by most texts |
82-
| SECONDARY_COLOR | Color used by city-weather app |
83-
| APP_CITY_WEATHER_APP_ID | Your [OpenWeathermap API Key](https://home.openweathermap.org/api_keys) |
84-
| APP_CITY_WEATHER_CITY_ID | The [City ID](https://openweathermap.org/find) for external weather data |
85-
| APP_CITY_WEATHER_UNITS | weather data unit forma ("metric" or "imperial") |
86-
| APP_CITY_WEATHER_MAX_CACHE_AGE | With an free OpenWeatherMap account the count of API requests is limited. How many minutes should the data cached? |
87-
| TZ | Timezone to show the correct time (e.g. "Europe/Berlin") |
74+
| Name | Required | Description |
75+
| ------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
76+
| TZ | X | Timezone to show the correct time (e.g. "Europe/Berlin") |
77+
| LOCALE | X | Country code for loading date time settings (e.g. "de") |
78+
| PRIMARY_COLOR | X | Color used by most texts |
79+
| SECONDARY_COLOR | x | Color used by city-weather app |
80+
| MQTT_SERVER | x | Address of the MQTT broker in format "mqtt://192.168.1.1:1883" |
81+
| MQTT_USERNAME | x | Username to access the MQTT Broker |
82+
| MQTT_PASSWORD | x | Password of the MQTT user |
83+
| APP_ITERATIONS | x | Number of seconds before switching to the next app |
84+
| APP_CITY_WEATHER_APP_ID | | Your [OpenWeathermap API Key](https://home.openweathermap.org/api_keys) |
85+
| APP_CITY_WEATHER_CITY_ID | | The [City ID](https://openweathermap.org/find) for external weather data |
86+
| APP_CITY_WEATHER_UNITS | | weather data unit forma ("metric" or "imperial") |
87+
| APP_CITY_WEATHER_MAX_CACHE_AGE | | With an free OpenWeatherMap account the count of API requests is limited. How many minutes should the data cached? |
88+
| HA_CITY_WEATHER_ENTITY_ID_TEMPERATURE | | |
89+
| HA_CITY_WEATHER_ENTITY_ID_HUMIDITY | | |
90+
| HA_CITY_WEATHER_MAX_AGE | | |
91+
| HA_BASE_API_URL | | URL to Home Assistant API |
92+
| HA_ACCESS_TOKEN | | Access token for Home Assistant API |
93+
| APP_CO2_SENSOR_ENTITY_ID | | Entity ID of the CO2 sensor |
94+
| APP_CO2_SENSOR_ALARM_THRESHOLD | | minimum sensor value to show the ventilate alarm on the display |

docker-compose.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,25 @@ services:
33
app:
44
image: mceddy/smartdisplay-server:latest
55
environment:
6+
LOCALE: 'de'
7+
TZ: 'Europe/Berlin'
8+
69
MQTT_SERVER: 'mqtt://localhost:1883'
710
MQTT_USERNAME: 'user'
811
MQTT_PASSWORD: 'password'
9-
LOCALE: 'de'
12+
1013
PRIMARY_COLOR: '#00C8C8'
1114
SECONDARY_COLOR: '#4CFF00'
12-
TZ: 'Europe/Berlin'
15+
1316
APP_CITY_WEATHER_CITY_ID: '2950159' # Berlin
1417
APP_CITY_WEATHER_APP_ID: 'your OpenWeather API key'
1518
APP_CITY_WEATHER_UNITS: 'metric'
1619
APP_CITY_WEATHER_MAX_CACHE_AGE: 30
1720
APP_ITERATIONS: 8
21+
22+
HA_BASE_API_URL: 'http://my-server.com/home-assistant/api'
23+
HA_ACCESS_TOKEN: 'your Home Assistant access token'
24+
25+
APP_CO2_SENSOR_ENTITY_ID: 'sensor.co2meter_value'
26+
APP_CO2_SENSOR_ALARM_THRESHOLD: 1200
1827
restart: unless-stopped

package-lock.json

Lines changed: 37 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
"author": "René Schimmelpfennig",
2121
"license": "MIT",
2222
"dependencies": {
23-
"axios": "^0.27.2",
23+
"axios": "^1.2.0",
2424
"clear": "^0.1.0",
2525
"color": "^4.2.3",
26-
"dayjs": "^1.11.5",
26+
"dayjs": "^1.11.6",
2727
"dotenv": "^16.0.3",
2828
"mqtt": "^4.3.7",
2929
"path": "^0.12.7"
@@ -38,4 +38,4 @@
3838
"ts-node": "^10.9.1",
3939
"typescript": "^4.8.4"
4040
}
41-
}
41+
}

src/apps/city-weather-ha.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { App } from './app';
2+
import { SmartDisplayController } from '../smart-display-controller';
3+
import { renderProgress, secondaryColor } from '../helper/draw';
4+
import { loadStateWithTimeCheck } from '../services/home-assistant-api';
5+
6+
const temperatureSensorEntityId =
7+
process.env.HA_CITY_WEATHER_ENTITY_ID_TEMPERATURE;
8+
const humiditySensorEntityId = process.env.HA_CITY_WEATHER_ENTITY_ID_HUMIDITY!;
9+
10+
const maxAgeMinutes = process.env.HA_CITY_WEATHER_MAX_AGE
11+
? parseInt(process.env.HA_CITY_WEATHER_MAX_AGE, 10)
12+
: undefined;
13+
14+
export class CityWeatherHaApp implements App {
15+
readonly name = 'city-weather';
16+
readonly renderOnlyOneTime = true;
17+
18+
private _temperature: number | null = null;
19+
private _humidity: number | null = null;
20+
21+
private _isDataLoading = false;
22+
23+
get isReady() {
24+
if (!this._temperature) {
25+
console.log('not ready because temperate has no value');
26+
return false;
27+
}
28+
29+
return true;
30+
}
31+
32+
constructor(private _controller: SmartDisplayController) {}
33+
34+
init() {
35+
this._loadData();
36+
}
37+
38+
reset() {
39+
this._loadData();
40+
}
41+
42+
render() {
43+
this._renderTemperature();
44+
this._renderHumidity();
45+
}
46+
47+
private async _loadData() {
48+
if (this._isDataLoading || !temperatureSensorEntityId) {
49+
return;
50+
}
51+
52+
this._isDataLoading = true;
53+
54+
try {
55+
const temperature = await loadStateWithTimeCheck(
56+
temperatureSensorEntityId,
57+
maxAgeMinutes
58+
);
59+
this._temperature = temperature;
60+
console.log('temperature', temperature);
61+
62+
if (humiditySensorEntityId) {
63+
const humidity = await loadStateWithTimeCheck(
64+
humiditySensorEntityId,
65+
maxAgeMinutes
66+
);
67+
this._humidity = humidity;
68+
console.log('humidity', humidity);
69+
}
70+
} catch (e) {
71+
console.error('problem on fetching sensor data', e);
72+
} finally {
73+
this._isDataLoading = false;
74+
}
75+
}
76+
77+
private _renderTemperature() {
78+
this._controller.drawText({
79+
hexColor: secondaryColor,
80+
text: `${this._temperature}°`,
81+
position: { x: 7, y: 1 },
82+
});
83+
}
84+
85+
private _renderHumidity() {
86+
renderProgress(this._controller, this._humidity);
87+
}
88+
}

src/apps/city-weather.ts renamed to src/apps/city-weather-owm.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import { App } from './app';
44
import { SmartDisplayController } from '../smart-display-controller';
55
import { renderPixelProgress, secondaryColor } from '../helper/draw';
66
import { roundToFixed } from '../helper/string';
7-
import { loadData } from '../services/open-weather-map';
7+
import { isConfigured, loadWeatherData } from '../services/open-weather-map';
88
import { CityWeatherData, LastUpdated } from '../models';
99

10-
export class CityWeatherApp implements App {
10+
const maxCacheAgeMinutes = parseInt(
11+
process.env.APP_CITY_WEATHER_MAX_CACHE_AGE || '0',
12+
10
13+
);
14+
15+
export class CityWeatherOwmApp implements App {
1116
private readonly _data = new LastUpdated<CityWeatherData>();
12-
private readonly _maxCacheAgeMinutes = parseInt(
13-
process.env.APP_CITY_WEATHER_MAX_CACHE_AGE || '0',
14-
10
15-
);
1617

1718
readonly name = 'city-weather';
1819
readonly renderOnlyOneTime = true;
@@ -28,7 +29,7 @@ export class CityWeatherApp implements App {
2829
return true;
2930
}
3031

31-
return cacheMinutesAge >= this._maxCacheAgeMinutes;
32+
return cacheMinutesAge >= maxCacheAgeMinutes;
3233
}
3334

3435
constructor(private _controller: SmartDisplayController) {}
@@ -62,7 +63,7 @@ export class CityWeatherApp implements App {
6263
renderPixelProgress(
6364
this._controller,
6465
this._calcCacheMinutesAge(),
65-
this._maxCacheAgeMinutes
66+
maxCacheAgeMinutes
6667
);
6768
}
6869

@@ -79,12 +80,17 @@ export class CityWeatherApp implements App {
7980

8081
private async _refreshWeatherData() {
8182
try {
82-
const data = await loadData();
83-
console.log('city weather', data);
83+
if (!isConfigured) {
84+
console.debug("skip city-weather-owm because isn't configured");
85+
return;
86+
}
87+
88+
const data = await loadWeatherData();
89+
console.debug('city weather', data);
8490

8591
this._data.value = data;
8692
} catch (error) {
87-
console.error("can't load openweathermap data", error);
93+
console.error("can't load open-weather-map data", error);
8894
}
8995
}
9096
}

0 commit comments

Comments
 (0)