add option to switch to the TwentyAfter Syntax and show UHR always
This commit is contained in:
		
							
								
								
									
										2
									
								
								interface/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								interface/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "esp8266-react",
 | 
					  "name": "wordclock",
 | 
				
			||||||
  "version": "0.1.0",
 | 
					  "version": "0.1.0",
 | 
				
			||||||
  "lockfileVersion": 1,
 | 
					  "lockfileVersion": 1,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,77 +1,91 @@
 | 
				
			|||||||
import React, { Component } from 'react';
 | 
					import React, { Component } from 'react';
 | 
				
			||||||
import { Typography, Box, List, ListItem, ListItemText } from '@material-ui/core';
 | 
					import {Typography, Switch} from '@material-ui/core';
 | 
				
			||||||
import { SectionContent } from '../components';
 | 
					import {
 | 
				
			||||||
 | 
					    BlockFormControlLabel,
 | 
				
			||||||
 | 
					    SectionContent,
 | 
				
			||||||
 | 
					    webSocketController,
 | 
				
			||||||
 | 
					    WebSocketControllerProps,
 | 
				
			||||||
 | 
					    WebSocketFormLoader,
 | 
				
			||||||
 | 
					    WebSocketFormProps
 | 
				
			||||||
 | 
					} from '../components';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DemoInformation extends Component {
 | 
					import {InformationState} from "./types";
 | 
				
			||||||
 | 
					import {WEB_SOCKET_ROOT} from "../api";
 | 
				
			||||||
 | 
					import {ValidatorForm} from "react-material-ui-form-validator";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const INFORMATION_WEBSOCKET_URL = WEB_SOCKET_ROOT + "information";
 | 
				
			||||||
 | 
					type InformationStateWebSocketControllerProps = WebSocketControllerProps<InformationState>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DemoInformation extends Component<InformationStateWebSocketControllerProps> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render() {
 | 
					  render() {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <SectionContent title='Demo Information' titleGutter>
 | 
					      <SectionContent title='WordClock Information' titleGutter>
 | 
				
			||||||
        <Typography variant="body1" paragraph>
 | 
					        <Typography variant="body1" paragraph>
 | 
				
			||||||
          This simple demo project allows you to control the built-in LED.
 | 
					          Welcome to the WordClock Overview page. Here you can turn on and off your WordClock and set Basic Settings
 | 
				
			||||||
          It demonstrates how the esp8266-react framework may be extended for your own IoT project.
 | 
					 | 
				
			||||||
        </Typography>
 | 
					        </Typography>
 | 
				
			||||||
        <Typography variant="body1" paragraph>
 | 
					        <WebSocketFormLoader
 | 
				
			||||||
          It is recommended that you keep your project interface code under the project directory.
 | 
					          {...this.props}
 | 
				
			||||||
          This serves to isolate your project code from the from the rest of the user interface which should
 | 
					          render={props => (
 | 
				
			||||||
          simplify merges should you wish to update your project with future framework changes.
 | 
					              <LightStateWebSocketControllerForm {...props} />
 | 
				
			||||||
        </Typography>
 | 
					          )}
 | 
				
			||||||
        <Typography variant="body1" paragraph>
 | 
					 | 
				
			||||||
          The demo project interface code is stored in the 'interface/src/project' directory:
 | 
					 | 
				
			||||||
        </Typography>        
 | 
					 | 
				
			||||||
        <List>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="ProjectMenu.tsx"
 | 
					 | 
				
			||||||
              secondary="You can add your project's screens to the side bar here."
 | 
					 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="ProjectRouting.tsx"
 | 
					 | 
				
			||||||
              secondary="The routing which controls the screens of your project."
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="DemoProject.tsx"
 | 
					 | 
				
			||||||
              secondary="This screen, with tabs and tab routing."
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="DemoInformation.tsx"
 | 
					 | 
				
			||||||
              secondary="The demo information page."
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="LightStateRestController.tsx"
 | 
					 | 
				
			||||||
              secondary="A form which lets the user control the LED over a REST service."
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="LightStateWebSocketController.tsx"
 | 
					 | 
				
			||||||
              secondary="A form which lets the user control and monitor the status of the LED over WebSockets."
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
          <ListItem>
 | 
					 | 
				
			||||||
            <ListItemText
 | 
					 | 
				
			||||||
              primary="LightMqttSettingsController.tsx"
 | 
					 | 
				
			||||||
              secondary="A form which lets the user change the MQTT settings for MQTT based control of the LED."
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </ListItem>
 | 
					 | 
				
			||||||
        </List>
 | 
					 | 
				
			||||||
        <Box mt={2}>
 | 
					 | 
				
			||||||
          <Typography variant="body1">
 | 
					 | 
				
			||||||
            See the project <a href="https://github.com/rjwats/esp8266-react/">README</a> for a full description of the demo project.
 | 
					 | 
				
			||||||
          </Typography>
 | 
					 | 
				
			||||||
        </Box>
 | 
					 | 
				
			||||||
      </SectionContent>
 | 
					      </SectionContent>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default DemoInformation;
 | 
					export default webSocketController(INFORMATION_WEBSOCKET_URL, 100, DemoInformation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type InformationWebSocketControllerFormProps = WebSocketFormProps<InformationState>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function LightStateWebSocketControllerForm(props: InformationWebSocketControllerFormProps) {
 | 
				
			||||||
 | 
					    const { data, saveData, setData } = props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const changeWordClockOn = (event: React.ChangeEvent<HTMLInputElement>) => {
 | 
				
			||||||
 | 
					        setData({wordclockOn: event.target.checked,twentyAfterSyntax: data.twentyAfterSyntax, uhrAlwaysOn: data.uhrAlwaysOn }, saveData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const changeTwentyAfterSyntax = (event: React.ChangeEvent<HTMLInputElement>) => {
 | 
				
			||||||
 | 
					        setData({wordclockOn: data.wordclockOn, twentyAfterSyntax: event.target.checked, uhrAlwaysOn: data.uhrAlwaysOn }, saveData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const changeUhrAlwaysOn = (event: React.ChangeEvent<HTMLInputElement>) => {
 | 
				
			||||||
 | 
					        setData({wordclockOn: data.wordclockOn,twentyAfterSyntax: data.twentyAfterSyntax, uhrAlwaysOn: event.target.checked }, saveData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ValidatorForm onSubmit={saveData}>
 | 
				
			||||||
 | 
					            <BlockFormControlLabel
 | 
				
			||||||
 | 
					                control={
 | 
				
			||||||
 | 
					                    <Switch
 | 
				
			||||||
 | 
					                        checked={data.wordclockOn}
 | 
				
			||||||
 | 
					                        onChange={changeWordClockOn}
 | 
				
			||||||
 | 
					                        color="primary"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                label="WordClock turned on?"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <BlockFormControlLabel
 | 
				
			||||||
 | 
					                control={
 | 
				
			||||||
 | 
					                    <Switch
 | 
				
			||||||
 | 
					                        checked={data.twentyAfterSyntax}
 | 
				
			||||||
 | 
					                        onChange={changeTwentyAfterSyntax}
 | 
				
			||||||
 | 
					                        color="primary"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                label="Use Twenty-After Syntax?"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <BlockFormControlLabel
 | 
				
			||||||
 | 
					                control={
 | 
				
			||||||
 | 
					                    <Switch
 | 
				
			||||||
 | 
					                        checked={data.uhrAlwaysOn}
 | 
				
			||||||
 | 
					                        onChange={changeUhrAlwaysOn}
 | 
				
			||||||
 | 
					                        color="primary"
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                label="Always Display UHR label"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					        </ValidatorForm>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,9 @@
 | 
				
			|||||||
export interface LightState {
 | 
					export interface LightState {
 | 
				
			||||||
  led_on: boolean;
 | 
					  led_on: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface InformationState {
 | 
				
			||||||
 | 
					  wordclockOn: boolean;
 | 
				
			||||||
 | 
					  twentyAfterSyntax: boolean;
 | 
				
			||||||
 | 
					  uhrAlwaysOn: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,10 +2,10 @@
 | 
				
			|||||||
// Created by lukas on 06.03.21.
 | 
					// Created by lukas on 06.03.21.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Clock.h"
 | 
					 | 
				
			||||||
#include "Types.h"
 | 
					#include "Types.h"
 | 
				
			||||||
 | 
					#include "Clock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Clock::Clock() : strip(NUMPIXELS, D5, NEO_GRB + NEO_KHZ800), animator(), refreshTicker() {
 | 
					Clock::Clock() : strip(NUMPIXELS, STRIPPIN, NEO_GRB + NEO_KHZ800), animator(), refreshTicker() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Clock::init() {
 | 
					void Clock::init() {
 | 
				
			||||||
@@ -28,13 +28,13 @@ void Clock::turnOn() {
 | 
				
			|||||||
  this->refreshTime();
 | 
					  this->refreshTime();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Clock::paintAllwaysOnLeds() {
 | 
					void Clock::paintAlwaysOnLeds() {
 | 
				
			||||||
  printWord(types::es, Adafruit_NeoPixel::Color(150, 150, 0));
 | 
					  printWord(types::es, Adafruit_NeoPixel::Color(150, 150, 0));
 | 
				
			||||||
  printWord(types::ist, Adafruit_NeoPixel::Color(150, 0, 150));
 | 
					  printWord(types::ist, Adafruit_NeoPixel::Color(150, 0, 150));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Clock::printWord(const std::vector<uint8_t>& word, uint32_t color) {
 | 
					void Clock::printWord(const std::vector<uint8_t>& word, uint32_t color) {
 | 
				
			||||||
  for (const int i : word) {
 | 
					  for (const uint8_t i : word) {
 | 
				
			||||||
    strip.setPixelColor(i, color);
 | 
					    strip.setPixelColor(i, color);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -54,17 +54,18 @@ void Clock::refreshTime() {
 | 
				
			|||||||
  const uint8_t hour = loctime->tm_hour;
 | 
					  const uint8_t hour = loctime->tm_hour;
 | 
				
			||||||
  const uint8_t minute = loctime->tm_min;
 | 
					  const uint8_t minute = loctime->tm_min;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  paintAllwaysOnLeds();
 | 
					  paintAlwaysOnLeds();
 | 
				
			||||||
  setTime(hour, minute);
 | 
					  setTime(hour, minute, this->twentyAfterSyntax, this->clockAlwaysOn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  strip.show();
 | 
					  strip.show();
 | 
				
			||||||
  Serial.printf("Time now: %sh %sM", &hour, &minute);
 | 
					  Serial.printf("Time now: %uh %uM\n", hour, minute);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Clock::setTime(uint8_t hour, uint8_t minute) {
 | 
					void Clock::setTime(uint8_t hour, uint8_t minute, bool twentyAfterSyntax, bool alwaysClockWord) {
 | 
				
			||||||
  const uint8_t minuteselector = minute / 5;
 | 
					  const uint8_t minuteselector = minute / 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // if minuteselector >= 4 +1 to hour
 | 
					  // if minuteselector >= 4 +1 to hour
 | 
				
			||||||
  if (minuteselector >= 4)
 | 
					  if (twentyAfterSyntax ? minuteselector >= 5 : minuteselector >= 4)
 | 
				
			||||||
    hour++;
 | 
					    hour++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // convert to 12h format
 | 
					  // convert to 12h format
 | 
				
			||||||
@@ -86,36 +87,69 @@ void Clock::setTime(uint8_t hour, uint8_t minute) {
 | 
				
			|||||||
             : hour == 0 || hour == 12 ? types::zwoelf
 | 
					             : hour == 0 || hour == 12 ? types::zwoelf
 | 
				
			||||||
                                       : hourWord;
 | 
					                                       : hourWord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  printWord(hourWord, Adafruit_NeoPixel::Color(0, 150, 0));
 | 
					  printWord(hourWord, Adafruit_NeoPixel::Color(0, 0, 150));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // print the minute words and the corresponding after/before half words
 | 
				
			||||||
 | 
					  printMinutes(minuteselector, twentyAfterSyntax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // uhr
 | 
				
			||||||
 | 
					  if (minuteselector == 0 || alwaysClockWord)
 | 
				
			||||||
 | 
					    printWord(types::uhr, Adafruit_NeoPixel::Color(150, 0, 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Clock::printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax) {
 | 
				
			||||||
  // fuenf / zehn / viertl word
 | 
					  // fuenf / zehn / viertl word
 | 
				
			||||||
  std::vector<uint8_t> minuteWord;
 | 
					  std::vector<uint8_t> minuteWord;
 | 
				
			||||||
  if (minuteselector == 1 || minuteselector == 5 || minuteselector == 7 || minuteselector == 11)
 | 
					  if (minuteSelector == 1 || minuteSelector == 5 || minuteSelector == 7 || minuteSelector == 11) {
 | 
				
			||||||
    minuteWord = types::fuenf;
 | 
					    minuteWord = types::fuenf;
 | 
				
			||||||
  else if (minuteselector == 2 || minuteselector == 4 || minuteselector == 8 || minuteselector == 10)
 | 
					  } else if (minuteSelector == 2 || minuteSelector == 4 || minuteSelector == 8 || minuteSelector == 10) {
 | 
				
			||||||
 | 
					    // check if we use the twenty after syntax
 | 
				
			||||||
 | 
					    if ((minuteSelector == 4 || minuteSelector == 8) && twentyAfterSyntax)
 | 
				
			||||||
 | 
					      minuteWord = types::zwanzig;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
      minuteWord = types::zehn;
 | 
					      minuteWord = types::zehn;
 | 
				
			||||||
  else if (minuteselector == 3)
 | 
					  } else if (minuteSelector == 3)
 | 
				
			||||||
    minuteWord = types::viertel;
 | 
					    minuteWord = types::viertel;
 | 
				
			||||||
  else if (minuteselector == 9)
 | 
					  else if (minuteSelector == 9)
 | 
				
			||||||
    minuteWord = types::dreiviertel;
 | 
					    minuteWord = types::dreiviertel;
 | 
				
			||||||
  else if (minuteselector == 6)
 | 
					  else if (minuteSelector == 6)
 | 
				
			||||||
    minuteWord = types::halb;
 | 
					    minuteWord = types::halb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  printWord(minuteWord, Adafruit_NeoPixel::Color(0, 150, 0));
 | 
					  printWord(minuteWord, Adafruit_NeoPixel::Color(0, 150, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // vor / nach
 | 
					  // vor / nach
 | 
				
			||||||
  std::vector<uint8_t> vornachWord;
 | 
					  std::vector<uint8_t> vornachWord;
 | 
				
			||||||
  if (minuteselector == 1 || minuteselector == 2 || minuteselector == 3 || minuteselector == 7 || minuteselector == 8)
 | 
					  if (minuteSelector == 1 || minuteSelector == 2 || minuteSelector == 3 ||
 | 
				
			||||||
 | 
					      ((minuteSelector == 8) &&
 | 
				
			||||||
 | 
					       !twentyAfterSyntax) ||  // check if twentyafter syntax is enabled - if not display the the after
 | 
				
			||||||
 | 
					      minuteSelector == 7 ||
 | 
				
			||||||
 | 
					      ((minuteSelector == 4) &&
 | 
				
			||||||
 | 
					       twentyAfterSyntax))  // check if twentyafter syntax is enabled - if yes display the the after
 | 
				
			||||||
    vornachWord = types::nach;
 | 
					    vornachWord = types::nach;
 | 
				
			||||||
  else if (minuteselector == 4 || minuteselector == 5 || minuteselector == 10 || minuteselector == 11)
 | 
					  else if (minuteSelector == 5 ||
 | 
				
			||||||
 | 
					           ((minuteSelector == 4) && !twentyAfterSyntax)  // check if twentyafter enabled if not -- display vor
 | 
				
			||||||
 | 
					           || minuteSelector == 10 || minuteSelector == 11 ||
 | 
				
			||||||
 | 
					           ((minuteSelector == 8) && twentyAfterSyntax))  // check if twentyafter enabled if yess -- display vor
 | 
				
			||||||
    vornachWord = types::vor;
 | 
					    vornachWord = types::vor;
 | 
				
			||||||
  printWord(vornachWord, Adafruit_NeoPixel::Color(150, 150, 150));
 | 
					  printWord(vornachWord, Adafruit_NeoPixel::Color(150, 150, 150));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // halb
 | 
					  // halb
 | 
				
			||||||
  if (minuteselector >= 4 && minuteselector <= 8)
 | 
					  if (minuteSelector >= 4 && minuteSelector <= 8) {
 | 
				
			||||||
 | 
					    // only 3 times if twentyafter syntax is on
 | 
				
			||||||
 | 
					    if (!twentyAfterSyntax || (minuteSelector >= 5 && minuteSelector <= 7))
 | 
				
			||||||
      printWord(types::halb, Adafruit_NeoPixel::Color(150, 0, 0));
 | 
					      printWord(types::halb, Adafruit_NeoPixel::Color(150, 0, 0));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  // uhr
 | 
					}
 | 
				
			||||||
  if (minuteselector == 0)
 | 
					
 | 
				
			||||||
    printWord(types::uhr, Adafruit_NeoPixel::Color(0, 0, 150));
 | 
					void Clock::useTwentyAfterSyntax(bool twentyAFterSyntax) {
 | 
				
			||||||
 | 
					  this->twentyAfterSyntax = twentyAFterSyntax;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Clock::useAlwaysOnUhrSyntax(bool alwaysOnUhr) {
 | 
				
			||||||
 | 
					  this->clockAlwaysOn = alwaysOnUhr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Clock::update() {
 | 
				
			||||||
 | 
					  if (refreshTicker.active())
 | 
				
			||||||
 | 
					    this->refreshTime();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								src/Clock.h
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/Clock.h
									
									
									
									
									
								
							@@ -5,22 +5,57 @@
 | 
				
			|||||||
#ifndef LEDSTRIPINTERFACE_CLOCK_H
 | 
					#ifndef LEDSTRIPINTERFACE_CLOCK_H
 | 
				
			||||||
#define LEDSTRIPINTERFACE_CLOCK_H
 | 
					#define LEDSTRIPINTERFACE_CLOCK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Arduino.h"
 | 
				
			||||||
#include <Ticker.h>
 | 
					#include <Ticker.h>
 | 
				
			||||||
#include "Adafruit_NeoPixel.h"
 | 
					#include "Adafruit_NeoPixel.h"
 | 
				
			||||||
#include "Arduino.h"
 | 
					#include "Arduino.h"
 | 
				
			||||||
#include "LoadAnimator.h"
 | 
					#include "LoadAnimator.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NUMPIXELS 108 // Popular NeoPixel ring size
 | 
					// define the strip length of the wordclock
 | 
				
			||||||
 | 
					#define NUMPIXELS 108
 | 
				
			||||||
 | 
					// define the esp pin the stip is attached to
 | 
				
			||||||
 | 
					#define STRIPPIN D5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Clock {
 | 
					class Clock {
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  Adafruit_NeoPixel strip{};
 | 
					  Adafruit_NeoPixel strip{};
 | 
				
			||||||
  LoadAnimator animator;
 | 
					  LoadAnimator animator;
 | 
				
			||||||
 | 
					  Ticker refreshTicker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void paintAllwaysOnLeds();
 | 
					  bool twentyAfterSyntax;
 | 
				
			||||||
 | 
					  bool clockAlwaysOn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * display the words which are always on (Es ist...)
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  void paintAlwaysOnLeds();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * paint a specific word
 | 
				
			||||||
 | 
					   * @param word word pointer to print
 | 
				
			||||||
 | 
					   * @param color the color in which to print it
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  void printWord(const std::vector<uint8_t>& word,  uint32_t color);
 | 
					  void printWord(const std::vector<uint8_t>& word,  uint32_t color);
 | 
				
			||||||
  void setTime(uint8_t hour, uint8_t minute);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * logic to print the correct minute word and its corresponding wods
 | 
				
			||||||
 | 
					   * @param minuteSelector a number between 0 - 11 representing the minute in 5min distances
 | 
				
			||||||
 | 
					   * @param twentyAfterSyntax whether to use a twenty after syntax or a 10min before half syntax
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  void printMinutes(uint8_t minuteSelector, bool twentyAfterSyntax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * set the whole time of the clock
 | 
				
			||||||
 | 
					   * @param hour hour to set (0-24)
 | 
				
			||||||
 | 
					   * @param minute minute to set(0-59)
 | 
				
			||||||
 | 
					   * @param twentyAfterSyntax whether to use a twenty after syntax or a 10min before half syntax
 | 
				
			||||||
 | 
					   * @param alwaysClockWord print the UHR word always and not only on full hours
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  void setTime(uint8_t hour, uint8_t minute, bool twentyAfterSyntax = false, bool alwaysClockWord = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * load the current time and set it onto the clock
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  void refreshTime();
 | 
					  void refreshTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
@@ -32,7 +67,7 @@ class Clock {
 | 
				
			|||||||
  void init();
 | 
					  void init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * turn of the wordclock
 | 
					   * turn off the wordclock
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  void turnOff();
 | 
					  void turnOff();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,7 +76,10 @@ class Clock {
 | 
				
			|||||||
   */
 | 
					   */
 | 
				
			||||||
  void turnOn();
 | 
					  void turnOn();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Ticker refreshTicker;
 | 
					  void useTwentyAfterSyntax(bool twentyAFterSyntax);
 | 
				
			||||||
 | 
					  void useAlwaysOnUhrSyntax(bool alwaysOnUhr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void update();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <HttpEndpoint.h>
 | 
					#include <HttpEndpoint.h>
 | 
				
			||||||
#include <MqttPubSub.h>
 | 
					 | 
				
			||||||
#include <WebSocketTxRx.h>
 | 
					#include <WebSocketTxRx.h>
 | 
				
			||||||
#include "Clock.h"
 | 
					#include "Clock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								src/InformationService.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/InformationService.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by lukas on 09.03.21.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "InformationService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					InformationService::InformationService(AsyncWebServer* server, SecurityManager* securityManager) :
 | 
				
			||||||
 | 
					    _webSocket(InformationState::read,
 | 
				
			||||||
 | 
					               InformationState::update,
 | 
				
			||||||
 | 
					               this,
 | 
				
			||||||
 | 
					               server,
 | 
				
			||||||
 | 
					               INFORMATION_SETTINGS_SOCKET_PATH,
 | 
				
			||||||
 | 
					               securityManager,
 | 
				
			||||||
 | 
					               AuthenticationPredicates::IS_AUTHENTICATED),
 | 
				
			||||||
 | 
					    clock() {
 | 
				
			||||||
 | 
					  // configure settings service update handler to update LED state
 | 
				
			||||||
 | 
					  addUpdateHandler([&](const String& originId) { onConfigUpdated(); }, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void InformationService::begin() {
 | 
				
			||||||
 | 
					  _state.wordClockOn = DEFAULT_CLOCK_STATE;
 | 
				
			||||||
 | 
					  _state.twentyAfterSyntax = true;
 | 
				
			||||||
 | 
					  _state.uhrAlwaysOn = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onConfigUpdated();
 | 
				
			||||||
 | 
					  clock.init();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void InformationService::onConfigUpdated() {
 | 
				
			||||||
 | 
					  //  digitalWrite(LED_PIN, _state.ledOn ? LED_ON : LED_OFF);
 | 
				
			||||||
 | 
					  if (_state.wordClockOn) {
 | 
				
			||||||
 | 
					    clock.turnOn();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    clock.turnOff();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  clock.useAlwaysOnUhrSyntax(_state.uhrAlwaysOn);
 | 
				
			||||||
 | 
					  clock.useTwentyAfterSyntax(_state.twentyAfterSyntax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  clock.update();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								src/InformationService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/InformationService.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by lukas on 09.03.21.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LEDSTRIPINTERFACE_INFORMATIONSERVICE_H
 | 
				
			||||||
 | 
					#define LEDSTRIPINTERFACE_INFORMATIONSERVICE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <HttpEndpoint.h>
 | 
				
			||||||
 | 
					#include <WebSocketTxRx.h>
 | 
				
			||||||
 | 
					#include "Clock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEFAULT_CLOCK_STATE true
 | 
				
			||||||
 | 
					#define OFF_STATE "OFF"
 | 
				
			||||||
 | 
					#define ON_STATE "ON"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define INFORMATION_SETTINGS_SOCKET_PATH "/ws/information"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InformationState {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  bool wordClockOn;
 | 
				
			||||||
 | 
					  bool twentyAfterSyntax;
 | 
				
			||||||
 | 
					  bool uhrAlwaysOn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static void read(InformationState& settings, JsonObject& root) {
 | 
				
			||||||
 | 
					    root["wordclockOn"] = settings.wordClockOn;
 | 
				
			||||||
 | 
					    root["twentyAfterSyntax"] = settings.twentyAfterSyntax;
 | 
				
			||||||
 | 
					    root["uhrAlwaysOn"] = settings.uhrAlwaysOn;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static StateUpdateResult update(JsonObject& root, InformationState& lightState) {
 | 
				
			||||||
 | 
					    const bool newOnState = root["wordclockOn"] | DEFAULT_CLOCK_STATE;
 | 
				
			||||||
 | 
					    const bool newTwentyAfterState = root["twentyAfterSyntax"] | DEFAULT_CLOCK_STATE;
 | 
				
			||||||
 | 
					    const bool newUhrAlwaysOnState = root["uhrAlwaysOn"] | DEFAULT_CLOCK_STATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (lightState.wordClockOn != newOnState || lightState.twentyAfterSyntax != newTwentyAfterState || lightState.uhrAlwaysOn != newUhrAlwaysOnState) {
 | 
				
			||||||
 | 
					      lightState.wordClockOn = newOnState;
 | 
				
			||||||
 | 
					      lightState.twentyAfterSyntax = newTwentyAfterState;
 | 
				
			||||||
 | 
					      lightState.uhrAlwaysOn = newUhrAlwaysOnState;
 | 
				
			||||||
 | 
					      return StateUpdateResult::CHANGED;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return StateUpdateResult::UNCHANGED;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  static void haRead(InformationState& settings, JsonObject& root) {
 | 
				
			||||||
 | 
					//    root["state"] = settings.wordClockOn ? ON_STATE : OFF_STATE;
 | 
				
			||||||
 | 
					//  }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//  static StateUpdateResult haUpdate(JsonObject& root, InformationState& lightState) {
 | 
				
			||||||
 | 
					//    String state = root["state"];
 | 
				
			||||||
 | 
					//    // parse new led state
 | 
				
			||||||
 | 
					//    boolean newState = false;
 | 
				
			||||||
 | 
					//    if (state.equals(ON_STATE)) {
 | 
				
			||||||
 | 
					//      newState = true;
 | 
				
			||||||
 | 
					//    } else if (!state.equals(OFF_STATE)) {
 | 
				
			||||||
 | 
					//      return StateUpdateResult::ERROR;
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//    // change the new state, if required
 | 
				
			||||||
 | 
					//    if (lightState.wordClockOn != newState) {
 | 
				
			||||||
 | 
					//      lightState.wordClockOn = newState;
 | 
				
			||||||
 | 
					//      return StateUpdateResult::CHANGED;
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//    return StateUpdateResult::UNCHANGED;
 | 
				
			||||||
 | 
					//  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InformationService : public StatefulService<InformationState>{
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  InformationService(AsyncWebServer* server, SecurityManager* securityManager);
 | 
				
			||||||
 | 
					  void begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 private:
 | 
				
			||||||
 | 
					  WebSocketTxRx<InformationState> _webSocket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Clock clock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void onConfigUpdated();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // LEDSTRIPINTERFACE_INFORMATIONSERVICE_H
 | 
				
			||||||
@@ -34,7 +34,7 @@ const std::vector<uint8_t> types::uhr = calcPixels(9, 8, 3);
 | 
				
			|||||||
uint8_t types::convert(uint8_t x, uint8_t y) {
 | 
					uint8_t types::convert(uint8_t x, uint8_t y) {
 | 
				
			||||||
  const bool upRow = (x % 2) == 0;
 | 
					  const bool upRow = (x % 2) == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int val = x * 9 + y;
 | 
					  uint8_t val = x * 9 + y;
 | 
				
			||||||
  // if its a row upwards we need to calculate the additional down and up pixels
 | 
					  // if its a row upwards we need to calculate the additional down and up pixels
 | 
				
			||||||
  if (upRow)
 | 
					  if (upRow)
 | 
				
			||||||
    // we need to go the rest down (9 -y) and up (*2) and subtract the too many added 10
 | 
					    // we need to go the rest down (9 -y) and up (*2) and subtract the too many added 10
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -1,5 +1,6 @@
 | 
				
			|||||||
#include <ESP8266React.h>
 | 
					#include <ESP8266React.h>
 | 
				
			||||||
#include "ClockService.h"
 | 
					#include "ClockService.h"
 | 
				
			||||||
 | 
					#include "InformationService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SERIAL_BAUD_RATE 115200
 | 
					#define SERIAL_BAUD_RATE 115200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9,18 +10,21 @@
 | 
				
			|||||||
AsyncWebServer server(80);
 | 
					AsyncWebServer server(80);
 | 
				
			||||||
ESP8266React esp8266React(&server);
 | 
					ESP8266React esp8266React(&server);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ClockService cservice = ClockService(&server, esp8266React.getSecurityManager());
 | 
					//ClockService cservice = ClockService(&server, esp8266React.getSecurityManager());
 | 
				
			||||||
 | 
					InformationService iservice = InformationService(&server, esp8266React.getSecurityManager());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setup() {
 | 
					void setup() {
 | 
				
			||||||
  // start serial and filesystem
 | 
					  // start serial and filesystem
 | 
				
			||||||
  Serial.begin(SERIAL_BAUD_RATE);
 | 
					  Serial.begin(SERIAL_BAUD_RATE);
 | 
				
			||||||
  Serial.printf("Starting WordClock %s", VERSION);
 | 
					  Serial.printf("Starting WordClock %s\n", VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // start the framework and demo project
 | 
					  // start the framework and demo project
 | 
				
			||||||
  esp8266React.begin();
 | 
					  esp8266React.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // load the initial light settings
 | 
					  // load the initial light settings
 | 
				
			||||||
  cservice.begin();
 | 
					//  cservice.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  iservice.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // start the server
 | 
					  // start the server
 | 
				
			||||||
  server.begin();
 | 
					  server.begin();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user