Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
|
This project is created in context of the lecture “Internet of Things Ecosystems” at the University of Applied Science Esslingen. It covers the invention of an own IoT Idea and Application from the scratch solving a real-world problem. In the design sprints the students learn about design, implementation (full-stack) and business aspects of Internet of Things applications.
IoT Prototyping FrameworkThe IoT Prototyping Framework (IoTPF) is a collection of tools, modules and samples with the aim to empower students and developers creating full-stack IoT prototypes in a short time period.
Contact:Idea and Application: Martin Dahm and Julian Maier
Lecture and IoTPF: dionysios.satikidis@gmail.com
Tools:
University of applied Sciences Esslingen 2018
StoryThis is a little story about the course "IoT Ecosystem" at the University of Applied Science Esslingen. During the course we had to design a IoT system that solves a concrete problem.
So this story is about "N.E.O." - the "Networkconnected Entrance Observator".
At the University of Applied Sciences Esslingen, location Flandernstraße there is a student managed Café. The Café is very popular because it's a cozy place with cheap prices for coffee and snacks. But the cafés opening hours are very flexible, as all students working there to make it possible in the first place do that voluntarily. So every now and then it's possible to find the cafés door closed. This is very annoying =(
IdeaOur idea is to publish the opening state of the café online. A customer should be able to check the opening state of the café via smartphone or computer. There is a direct mapping between the open door of the café and the café state in general. So all we have to do is detecting the door state and publish it online.
The café employees should also be able to control the café state e.g. during tidying the café in the evening or team meetings in the summer.
Solution- Detect the door state
- Send café state events to the Particle Cloud
- Publish café state via Losant-Dashboards or Telegram-Bot
We use a magnetic sensor (the SparkFun LSM9DS1) and a permanent magnet for the door state detection. The magnetic values have the advantage that we don't need any kind of historic values, as we can detect directly if the door is open or closed. Additionally it is very easy to configure the system at different doors. The system needs a calibration phase for teaching the state "open" and "closed" - simply remembering the three axis values of the magnetic sensor.
On the Particle Photon, a state machine is running that periodically polls the sensor values and generates events according to the door state.
In Losant, the Particle Events trigger a workflow to convert the Particle format to a format that's understandable for the Losant-Dashboard. Another workflow monitors the particle in general to detect a possible offline state of the system.
The left dashboard shows the customer view (currently with the "system offline" screen). It is a public dashboard so everyone with the right URL has access. The dashboard on the right side is for the café employees. It is the interface for calibration and locking the café state.
To realize push notifications we decide to implement a Bot for the Telegram Messenger. The Particle Cloud and Telegram offer both a REST API for easy access. The Bot logic itself is implemented as a python3 script and offers a limited functionality for subscribe, unsubscripte and polling from the N.E.O. system.
- Particle Cloud: https://docs.particle.io/reference/api/
- Telegram Bots: https://core.telegram.org/bots/api
To become more familiar with the problem and the needs of the customers and employees we used different communication channels. We got a clearer view through live demonstrations of our prototype and an online user survey.
We experienced a lot of different aspects during this IoT project. Our assistant professor trained us to not only think in the boundary of a technical solution.
The system N.E.O. will go online during the next term at the HZE Café.
Julian Maier, Martin Dahm
Check out if the HZE Café is open: Link-to-site
Read more about the HZE Café: http://www.hs-esslingen.de/de/hochschule/service/campusleben/hze-cafe-flandernstrasse.html
/*
* This file is a sample application, based
* on the IoT Prototyping Framework (IoTPF)
This application and IoTPF is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IoTPF is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU v3 General Public License for more details.
Released under GNU v3
You should have received a copy of the GNU General Public License
along with IoTPF. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This is the the N.E.O. particle application
* IoTPF 2018
* @author dionysios.satikidis(dionysios.satikidis@gmail.com)
* @version 1.0
* N. E. O. 2018
* @author Julian Maier, Martin Dahm
* @version 1.1
*/
// This #include statement was automatically added by the Particle IDE.
#include <SparkFunLSM9DS1.h>
#include <limits>
#define CALIBRATIONTIME 1500
#define OPENDELAY 10000
#define RESENDTIME 5000
int buttonPin = D3;
int StatusLedPin = D7;
unsigned long timestamp;
unsigned long resendTimestamp;
int hysteresis = 5000;
String closeCalStr = "";
String openCalStr = "";
String magValuesStr = "";
String statusMsg = "offline";
int doorState = 0;
int cafeLockState = 0;
int remoteCalibration = 0;
struct MagData{
int16_t magx;
int16_t magy;
int16_t magz;
};
MagData currentMagValues;
struct DoorCalibration{
int16_t Threshold_X_Min;
int16_t Threshold_X_Max;
int16_t Threshold_Y_Min;
int16_t Threshold_Y_Max;
int16_t Threshold_Z_Min;
int16_t Threshold_Z_Max;
};
DoorCalibration openCalibrationValues;
DoorCalibration closeCalibrationValues;
typedef enum APPSTATE{CALIBRATION, WORK} APPSTATE_TYPE;
typedef enum DOORSTATE{DOOR_OPEN, DOOR_CLOSE} DOORSTATE_TYPE;
typedef enum CALIBRATIONSTATE{OPEN, CLOSE, SAVE_OPEN, SAVE_CLOSE} CALIBRATIONSTATE_TYPE;
typedef enum CAFESTATE{CAFE_OPENED,CAFE_OPENING,CAFE_CLOSED,CAFE_LOCKED} CAFESTATE_TYPE;
APPSTATE_TYPE actAppState = CALIBRATION;
CALIBRATIONSTATE_TYPE calibrationState = CLOSE;
DOORSTATE_TYPE actDoorState = DOOR_OPEN;
DOORSTATE_TYPE nextDoorState = DOOR_OPEN;
CAFESTATE_TYPE actCafeState = CAFE_CLOSED;
CAFESTATE_TYPE nextCafeState = CAFE_CLOSED;
LSM9DS1 imu;
#define LSM9DS1_M 0x1E // Would be 0x1C if SDO_M is LOW
#define LSM9DS1_AG 0x6B // Would be 0x6A if SDO_AG is LOW
bool buttonIsPressed(){
return (digitalRead(buttonPin) == 0);
}
bool buttonIsReleased(){
return (digitalRead(buttonPin) == 1);
}
bool timeElapsed(unsigned long stamp, unsigned int limit){
return ((millis() - stamp) >= limit);
}
void blink(uint8_t repeat){
for(uint8_t i = 0; i < repeat; i++){
digitalWrite(StatusLedPin, HIGH);
delay(200);
digitalWrite(StatusLedPin, LOW);
delay(200);
}
}
void printCalibration(){
Particle.publish("Open X(min,max),Y(min,max),Z(min,max)",
"X(" + String(openCalibrationValues.Threshold_X_Min) + "," + String(openCalibrationValues.Threshold_X_Max) + "),"
+ "Y(" + String(openCalibrationValues.Threshold_Y_Min) + "," + String(openCalibrationValues.Threshold_Y_Max) + "),"
+ "Z(" + String(openCalibrationValues.Threshold_Z_Min) + "," + String(openCalibrationValues.Threshold_Z_Max) + ")");
delay(500);
Particle.publish("Close X(min,max),Y(min,max),Z(min,max)",
"X(" + String(closeCalibrationValues.Threshold_X_Min) + "," + String(closeCalibrationValues.Threshold_X_Max) + "),"
+ "Y(" + String(closeCalibrationValues.Threshold_Y_Min) + "," + String(closeCalibrationValues.Threshold_Y_Max) + "),"
+ "Z(" + String(closeCalibrationValues.Threshold_Z_Min) + "," + String(closeCalibrationValues.Threshold_Z_Max) + ")");
}
void printCurrentMagValues(){
Particle.publish("MAG X,Y,Z", String(currentMagValues.magx) + "," + String(currentMagValues.magy) + "," +String(currentMagValues.magz) );
}
void saveCalibration(DoorCalibration *calData){
int temp = currentMagValues.magx;
calData->Threshold_X_Max = (temp + hysteresis) >= std::numeric_limits<int16_t>::max() ?
std::numeric_limits<int16_t>::max() : temp + hysteresis;
calData->Threshold_X_Min = (temp - hysteresis) <= std::numeric_limits<int16_t>::min() ?
std::numeric_limits<int16_t>::min() : temp - hysteresis;
temp = currentMagValues.magy;
calData->Threshold_Y_Max = (temp + hysteresis) >= std::numeric_limits<int16_t>::max() ?
std::numeric_limits<int16_t>::max() : temp + hysteresis;
calData->Threshold_Y_Min = (temp - hysteresis) <= std::numeric_limits<int16_t>::min() ?
std::numeric_limits<int16_t>::min() : temp - hysteresis;
temp = currentMagValues.magz;
calData->Threshold_Z_Max = (temp + hysteresis) >= std::numeric_limits<int16_t>::max() ?
std::numeric_limits<int16_t>::max() : temp + hysteresis;
calData->Threshold_Z_Min = (temp - hysteresis) <= std::numeric_limits<int16_t>::min() ?
std::numeric_limits<int16_t>::min() : temp - hysteresis;
}
String getOpenCalibrationString(){
return "Open - X(" + String(openCalibrationValues.Threshold_X_Min) + "," + String(openCalibrationValues.Threshold_X_Max) + "),"
+ "Y(" + String(openCalibrationValues.Threshold_Y_Min) + "," + String(openCalibrationValues.Threshold_Y_Max) + "),"
+ "Z(" + String(openCalibrationValues.Threshold_Z_Min) + "," + String(openCalibrationValues.Threshold_Z_Max) + ")";
}
String getCloseCalibrationString(){
return "Close - X(" + String(closeCalibrationValues.Threshold_X_Min) + "," + String(closeCalibrationValues.Threshold_X_Max) + "),"
+ "Y(" + String(closeCalibrationValues.Threshold_Y_Min) + "," + String(closeCalibrationValues.Threshold_Y_Max) + "),"
+ "Z(" + String(closeCalibrationValues.Threshold_Z_Min) + "," + String(closeCalibrationValues.Threshold_Z_Max) + ")";
}
String getMagValuesString(){
return String(currentMagValues.magx) + "," + String(currentMagValues.magy) + "," + String(currentMagValues.magz);
}
bool isDoorOpened(){
bool retResult = true;
retResult &= (currentMagValues.magx >= openCalibrationValues.Threshold_X_Min && currentMagValues.magx <= openCalibrationValues.Threshold_X_Max);
retResult &= (currentMagValues.magy >= openCalibrationValues.Threshold_Y_Min && currentMagValues.magy <= openCalibrationValues.Threshold_Y_Max);
retResult &= (currentMagValues.magz >= openCalibrationValues.Threshold_Z_Min && currentMagValues.magz <= openCalibrationValues.Threshold_Z_Max);
return retResult;
}
bool isDoorClosed(){
bool retResult = true;
retResult &= (currentMagValues.magx >= closeCalibrationValues.Threshold_X_Min && currentMagValues.magx <= closeCalibrationValues.Threshold_X_Max);
retResult &= (currentMagValues.magy >= closeCalibrationValues.Threshold_Y_Min && currentMagValues.magy <= closeCalibrationValues.Threshold_Y_Max);
retResult &= (currentMagValues.magz >= closeCalibrationValues.Threshold_Z_Min && currentMagValues.magz <= closeCalibrationValues.Threshold_Z_Max);
return retResult;
}
int remoteCall(String info){
if(info == "losant"){
switch(actAppState){
case CALIBRATION:{
remoteCalibration = 1;
return 0;
break;
}
case WORK:{
// toogle cafeLockState
cafeLockState = (cafeLockState == 1) ? 0 : 1;
return 0;
break;
}
default:
break;
}
}
return 1;
}
void readMagValues(){
imu.readMag();
currentMagValues.magx = imu.mx;
currentMagValues.magy = imu.my;
currentMagValues.magz = imu.mz;
}
void setup() {
Particle.publish("Setup Start ...", 1);
pinMode(StatusLedPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
imu.settings.device.commInterface = IMU_MODE_I2C;
imu.settings.device.mAddress = LSM9DS1_M;
imu.settings.device.agAddress = LSM9DS1_AG;
// Try to initialise and warn if we couldn't detect the chip
if (!imu.begin())
{
Particle.publish("[Debug] Oops ... unable to initialize the LSM9DS1. Check your wiring!", 0);
}
else{
Particle.publish("[Debug] LSM9DS1 ready", 1);
}
readMagValues();
String magString = String(currentMagValues.magx) + "-" + String(currentMagValues.magy) + "-" + String(currentMagValues.magz);
Particle.publish("[Debug]", magString);
Particle.variable("openCalStr", openCalStr);
Particle.variable("closeCalStr", closeCalStr);
Particle.variable("magValuesStr", magValuesStr);
Particle.variable("statusMsg",statusMsg);
Particle.function("remoteCall", remoteCall);
Particle.publish("Done!", 1);
}
void transitionDoor(){
nextDoorState = actDoorState;
switch(actDoorState){
case DOOR_OPEN:{
if(isDoorClosed()){
nextDoorState = DOOR_CLOSE;
}
break;
}
case DOOR_CLOSE:{
if(isDoorOpened()){
nextDoorState = DOOR_OPEN;
}
break;
}
}
// if the state is changing...
if(nextDoorState!=actDoorState){
// Exit actual state
switch(actDoorState){
case DOOR_OPEN:{
break;
}
case DOOR_CLOSE:{
break;
}
}
// Enter next state
switch(nextDoorState){
case DOOR_OPEN:{
digitalWrite(StatusLedPin,HIGH);
doorState = 1;
break;
}
case DOOR_CLOSE:{
digitalWrite(StatusLedPin,LOW);
doorState = 0;
break;
}
}
}
// Stay in the same State
if(nextDoorState==actDoorState){
switch(actDoorState){
case DOOR_OPEN:{
break;
}
case DOOR_CLOSE:{
break;
}
}
}
actDoorState = nextDoorState;
}
void transitionCafe(){
nextCafeState = actCafeState;
switch(actCafeState){
case CAFE_OPENED :{
if(cafeLockState == 1){
nextCafeState = CAFE_LOCKED;
}
else if(actDoorState == DOOR_CLOSE){
nextCafeState = CAFE_CLOSED;
}
break;
}
case CAFE_CLOSED:{
if(cafeLockState == 1){
nextCafeState = CAFE_LOCKED;
}
else if(actDoorState == DOOR_OPEN){
nextCafeState = CAFE_OPENING;
}
break;
}
case CAFE_LOCKED:{
if(cafeLockState == 0){
if(actDoorState == DOOR_OPEN){
nextCafeState = CAFE_OPENING;
}
else if(actDoorState == DOOR_CLOSE){
nextCafeState = CAFE_CLOSED;
}
}
break;
}
case CAFE_OPENING:{
if(cafeLockState == 1){
nextCafeState = CAFE_LOCKED;
}
else if(actDoorState == DOOR_OPEN && timeElapsed(timestamp,OPENDELAY)){
nextCafeState = CAFE_OPENED;
}
break;
}
}
// if the state is changing...
if(nextCafeState!=actCafeState){
// Exit actual state
switch(actCafeState){
case CAFE_OPENED:{
break;
}
case CAFE_CLOSED:{
break;
}
case CAFE_LOCKED:{
break;
}
}
// Enter next state
switch(nextCafeState){
case CAFE_OPENED:{
statusMsg = "open";
Particle.publish("statusMessage",statusMsg);
resendTimestamp = millis();
break;
}
case CAFE_CLOSED:{
statusMsg = "close";
Particle.publish("statusMessage",statusMsg);
resendTimestamp = millis();
break;
}
case CAFE_LOCKED:{
statusMsg = "lock";
Particle.publish("statusMessage",statusMsg);
resendTimestamp = millis();
break;
}
case CAFE_OPENING:{
timestamp = millis();
break;
}
}
}
// Stay in the same State
if(nextCafeState==actCafeState){
switch(actCafeState){
case CAFE_OPENED:{
if(timeElapsed(resendTimestamp,RESENDTIME)){
statusMsg = "open";
Particle.publish("statusMessage",statusMsg);
resendTimestamp = millis();
}
break;
}
case CAFE_CLOSED:{
if(timeElapsed(resendTimestamp,RESENDTIME)){
statusMsg = "close";
Particle.publish("statusMessage",statusMsg);
resendTimestamp = millis();
}
break;
}
case CAFE_LOCKED:{
if(timeElapsed(resendTimestamp,RESENDTIME)){
statusMsg = "lock";
Particle.publish("statusMessage",statusMsg);
resendTimestamp = millis();
}
break;
}
case CAFE_OPENING:{
break;
}
}
}
actCafeState = nextCafeState;
}
void loop() {
if(actAppState == CALIBRATION){
timeElapsed(timestamp,CALIBRATIONTIME) ? digitalWrite(StatusLedPin,LOW) : digitalWrite(StatusLedPin,HIGH);
}
switch(actAppState){
case CALIBRATION:{
switch(calibrationState){
case OPEN:{
if(buttonIsPressed() || remoteCalibration == 1){
digitalWrite(StatusLedPin,HIGH);
calibrationState = SAVE_OPEN;
timestamp = millis();
}
Particle.publish("statusMessage","Open the door and confirm!");
break;
}
case CLOSE:{
if(buttonIsPressed() || remoteCalibration == 1){
digitalWrite(StatusLedPin,HIGH);
calibrationState = SAVE_CLOSE;
timestamp = millis();
}
Particle.publish("statusMessage","Close the door and confirm!");
break;
}
case SAVE_OPEN:{
if((buttonIsReleased() && timeElapsed(timestamp,CALIBRATIONTIME))
|| remoteCalibration == 1){
readMagValues();
saveCalibration(&openCalibrationValues);
openCalStr = getOpenCalibrationString();
actAppState = WORK;
remoteCalibration = 0;
Particle.publish("statusMessage","Open done!");
blink(2);
}
else if (buttonIsReleased() && !timeElapsed(timestamp,CALIBRATIONTIME))
{
Particle.publish("statusMessage","Error");
calibrationState = OPEN;
}
break;
}
case SAVE_CLOSE:{
if((buttonIsReleased() && timeElapsed(timestamp,CALIBRATIONTIME))
|| remoteCalibration == 1){
readMagValues();
saveCalibration(&closeCalibrationValues);
closeCalStr = getCloseCalibrationString();
calibrationState = OPEN;
remoteCalibration = 0;
Particle.publish("statusMessage","Close done!");
blink(2);
}
else if (buttonIsReleased() && !timeElapsed(timestamp,CALIBRATIONTIME))
{
Particle.publish("statusMessage","Error");
calibrationState = CLOSE;
}
break;
}
}
break;
}
case WORK:{
readMagValues();
magValuesStr = getMagValuesString();
transitionDoor();
transitionCafe();
break;
} }
delay(1000);
}
#
# This file is a sample application, based
# on the IoT Prototyping Framework (IoTPF)
# This application and IoTPF is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IoTPF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU v3 General Public License for more details.
# Released under GNU v3
# You should have received a copy of the GNU General Public License
# along with IoTPF. If not, see <http://www.gnu.org/licenses/>.
#
#
# This the telegram chatbot
#
# IoTPF 2018
# @author dionysios.satikidis(dionysios.satikidis@gmail.com)
# @version 1.0
#
# N. E. O. 2018
# @author Julian Maier, Martin Dahm
# @version 1.1
#/
#!/usr/bin/python3
import urllib.request
import urllib.error
from socket import timeout
from urllib.parse import quote
import json
from pprint import pprint
import threading
import sqlite3
import time
exit_flag = 0;
exit_flag_mutex = threading.Lock()
looptime = 5;
update_mutex = threading.Lock()
class ParticleThread (threading.Thread):
def __init__(self, name, device_id, access_token):
threading.Thread.__init__(self)
self.name = name
self.device_id = device_id
self.access_token = access_token
self.stop_thread = 0
self.cafe_state = 'offline'
def poll_Cafe_State(self):
request = 'https://api.particle.io/v1/devices/{0}/statusMsg?access_token={1}'.format(self.device_id,self.access_token)
try:
with urllib.request.urlopen(request,timeout=10) as response:
resp = json.loads(response.read().decode('utf-8'))
return resp['result']
except timeout:
return "offline"
def get_Cafe_State(self):
return self.cafe_state
def run(self):
print("Thread<{0}>: Start...".format(self.name))
while(self.stop_thread == 0):
self.cafe_state = self.poll_Cafe_State()
if self.cafe_state == 'lock':
self.cafe_state = 'close'
print(self.cafe_state)
time.sleep(10)
with exit_flag_mutex:
if exit_flag != 0:
self.stop_thread = 1
print("Thread<{0}>: ...End".format(self.name))
class TelegramThread (threading.Thread):
def __init__(self, name, db_file, telegram_bot_token):
threading.Thread.__init__(self)
self.name = name
self.db_file = db_file
self.telegram_bot_token = telegram_bot_token
self.stop_thread = 0
self.update_id_offset = 0
self.user_table = "neo_user"
self.new_notification = False
self.cafe_state = "offline"
self.CafeThread = ParticleThread("NEO","<YOUR_DEVICE_ID>","<YOUR_ACCESS_TOKEN>")
def run(self):
print("Thread<{0}>: Start...".format(self.name))
self.CafeThread.start()
while self.stop_thread == 0:
loop_timestamp = time.time()
with exit_flag_mutex:
if exit_flag != 0:
self.stop_thread = 1
self.check_state()
print("notification: {0}, state: {1}".format(self.new_notification,self.cafe_state))
if self.new_notification:
self.send_notification()
self.get_Telegram_Updates()
loop_timestamp_diff = time.time() - loop_timestamp
print(looptime - loop_timestamp_diff)
if looptime - loop_timestamp_diff >= 0:
time.sleep(looptime - loop_timestamp_diff)
print("Thread<{0}>: ...End".format(self.name))
self.CafeThread.join()
def send_notification(self):
connection = sqlite3.connect(self.db_file)
notification_user = self.select_notification_user(connection)
print("notification user: {0}".format(notification_user))
connection.commit()
connection.close()
text = self.cafe_state_text()
for user in notification_user:
self.send_Telegram_Message(user[0],text)
def check_state(self):
state = self.CafeThread.get_Cafe_State()
if(self.cafe_state != state):
self.cafe_state = state
self.new_notification = True
else:
self.new_notification = False
def get_Telegram_Updates(self):
request = 'https://api.telegram.org/bot{0}/getUpdates{1}'.format(self.telegram_bot_token,self.add_offset())
with urllib.request.urlopen(request) as response:
resp = json.loads(response.read().decode('utf-8'))
if resp['ok']:
result_list = resp['result']
for result in result_list:
chat_id = result['message']['from']['id']
first_name = result['message']['from']['first_name']
user_text = result['message']['text']
self.update_id_offset = result['update_id']+1
connection = sqlite3.connect(self.db_file)
self.create_Table(connection)
if not self.check_subscriber(connection,chat_id):
self.add_user(connection, chat_id, first_name)
if user_text == "/start":
self.send_Welcome(chat_id,first_name)
self.send_Help(chat_id)
elif user_text == "/tellme":
self.update_notification(connection,chat_id,True)
self.send_notification_status(True,chat_id)
elif user_text == "/shutup":
self.update_notification(connection,chat_id,False)
self.send_notification_status(False,chat_id)
elif user_text == "/ask":
self.send_cafe_state(chat_id)
elif user_text == "/aktuellesfischangebot":
self.send_fisch(chat_id)
elif user_text == "/help":
self.send_Help(chat_id)
else:
self.send_dont_understand(chat_id)
self.send_Help(chat_id)
connection.commit()
connection.close()
print("{0}-{1}-{2}-{3}".format(chat_id,user_text,self.update_id_offset,first_name))
connection = sqlite3.connect(self.db_file)
pprint(self.select_all(connection))
connection.commit()
connection.close()
def cafe_state_text(self):
if self.cafe_state == "close":
text = """Das Cafe ist zu."""
elif self.cafe_state == "open":
text = """Das Cafe ist offen."""
else:
text = """Das System ist leider gerade offline."""
return text
def send_cafe_state(self,chat_id):
text = self.cafe_state_text()
self.send_Telegram_Message(chat_id,text)
def send_fisch(self,chat_id):
text = """Ich habe leider keinen Fisch für dich!"""
self.send_Telegram_Message(chat_id,text)
def send_Help(self, chat_id):
text = """Optionen:
/ask - HZE Cafe Status
/tellme - HZE Cafe Status auto
/shutup - NEO Bot ist still
/aktuellesfischangebot - Fisch"""
self.send_Telegram_Message(chat_id,text)
def send_notification_status(self, state, chat_id):
if state:
text = """Alles klar. Ich sage dir bescheid."""
else:
text = """Ok. Ich bin ruhig."""
self.send_Telegram_Message(chat_id,text)
def send_dont_understand(self, chat_id):
text = """Sorry, ich verstehe dich nicht.
Versuchs doch mal mit..."""
self.send_Telegram_Message(chat_id,text)
def send_Welcome(self, chat_id,first_name):
text = """Hallo {0}, ich bin NEO =) Ich kann dir bescheid sagen, ob das HZE Cafe gerade auf oder zu ist.
Entweder fragst du mich oder ich sag dir einfach automatisch bescheid wenn sich etwas ändert""".format(first_name)
self.send_Telegram_Message(chat_id,text)
def add_offset(self):
return "?offset={0}".format(self.update_id_offset)
def check_subscriber(self,dbcon, chat_id):
selected_id_list = self.select_chat_id(dbcon, chat_id)
if len(selected_id_list) == 0:
return False
else:
return True
def add_user(self,dbcon,chat_id,first_name):
dbcur = dbcon.cursor()
dbcur.execute("INSERT INTO {0} (chat_id,first_name,notification) VALUES ({1}, '{2}', 0)".format(self.user_table,chat_id,first_name))
dbcur.close()
def update_notification(self,dbcon,chat_id,state):
if state:
value = 1
else:
value = 0
dbcur = dbcon.cursor()
dbcur.execute("UPDATE {0} SET notification = {1} WHERE chat_id = {2}".format(self.user_table,value,chat_id))
dbcur.close()
def select_notification_user(self,dbcon):
dbcur = dbcon.cursor()
dbcur.execute("SELECT * FROM {0} where notification = 1".format(self.user_table))
select_result = dbcur.fetchall()
dbcur.close()
return select_result
def create_Table(self, dbcon):
dbcur = dbcon.cursor()
dbcur.execute("CREATE TABLE IF NOT EXISTS {0}(chat_id INT, first_name TEXT, notification INT)".format(self.user_table))
dbcur.close()
def select_all(self, dbcon):
dbcur = dbcon.cursor()
dbcur.execute("SELECT * FROM {0}".format(self.user_table))
select_result = dbcur.fetchall()
dbcur.close()
return select_result
def select_chat_id(self,dbcon, chat_id):
dbcur = dbcon.cursor()
dbcur.execute("SELECT * FROM {0} where chat_id = {1}".format(self.user_table,chat_id))
select_result = dbcur.fetchall()
dbcur.close()
return select_result
def send_Telegram_Message(self,chat_id,text):
#print("id: {0} -> text: {1}".format(chat_id,text))
#return 0
request = 'https://api.telegram.org/bot{0}/sendMessage?chat_id={1}&text={2}'.format(self.telegram_bot_token,chat_id,quote(text))
print(request)
with urllib.request.urlopen(request) as response:
None
return 0
# Create new threads
bot = TelegramThread("NeoBot","sub.db",'<YOUR_TELEGRAM_BOT_TOKEN>')
# Start new Threads
bot.start()
input("Press Enter to continue...")
with exit_flag_mutex:
exit_flag = 1
bot.join()
print ("Exiting Main Thread")
<!--
# This file is a sample application, based
# on the IoT Prototyping Framework (IoTPF)
# This application and IoTPF is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IoTPF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU v3 General Public License for more details.
# Released under GNU v3
# You should have received a copy of the GNU General Public License
# along with IoTPF. If not, see <http://www.gnu.org/licenses/>.
#
#
# This the losant application
#
# IoTPF 2018
# @author dionysios.satikidis(dionysios.satikidis@gmail.com)
# @version 1.0
#
# N. E. O. 2018
# @author Julian Maier, Martin Dahm
# @version 1.1
-->
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>HZE Cafe</title>
<link rel="stylesheet" href="css/styles.css?v=1.0">
</head>
<body>
<!--
Begin Losant Embed
Drop this in your markup where you would like the widget to go.
-->
<a class="los-widget"
href="https://app.losant.com/dashboards/5a50ca4484f81800061e64ca?embed=mJILcu7JTR"
data-dashboard-id="5a50ca4484f81800061e64ca"
data-block-id="mJILcu7JTR"
data-theme="dark"
data-height="400px"
data-width="100%">
View my Losant-powered widget "HZE Cafe"
</a>
<script>window.lsnt = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0], t = window.lsnt || {};
if (d.getElementById(id)) return t;
js = d.createElement(s); js.id = id;
js.src = "https://app.losant.com/scripts/widgets.js";
fjs.parentNode.insertBefore(js, fjs); t._e = [];
t.ready = function(f) { t._e.push(f); }; return t;
}(document, "script", "lsnt-widgets"));</script>
<img src='https://chart.googleapis.com/chart?cht=qr&chl=http%3A%2F%2Fwww2.hs-esslingen.de%2F~madait02%2F&chs=180x180&choe=UTF-8&chld=L|2' alt='qr code'><a href='http://www.qrcode-generator.de' border='0' style='cursor:default' rel='nofollow'></a>
</body>
</html>
Comments