A TeamDionysios Satikidis
Published © GPL3+

N.E.O.

A Network-connected Entrance Observator.

IntermediateWork in progress310
N.E.O.

Things used in this project

Hardware components

Photon
Particle Photon
×1
SparkFun 9 Degrees of Freedom IMU Breakout - LSM9DS1
SparkFun 9 Degrees of Freedom IMU Breakout - LSM9DS1
×1
Breadboard (generic)
Breadboard (generic)
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1

Software apps and online services

Losant Platform
Losant Platform
Telegram

Story

Read more

Schematics

Prototyp

Neo steckplatine syip0q4x7g

Code

Particle Photon Logic

C/C++
Read magatic values and create events.
/*
 *  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);   
}

Telegram Bot Prototype

Python
Early prototype for premium use
#
#  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")

Losant Dashboard - Website

HTML
HZE Cafe State for free
<!--
#  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>

Credits

A Team

A Team

1 project • 0 followers
Dionysios Satikidis

Dionysios Satikidis

0 projects • 0 followers
Work at Festo for Innovation Projects. Lecturer Embedded Systems & IoT Ecosystems at Brunel Univ. and Univ. of Applied Sciences Esslingen.
Thanks to Dionysios Satikidis.

Comments

Add projectSign up / Login