Arduino
(1) traffic_light.ino
```
#include <TrafficLight.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <Timer.h>
// Module connection pins (Digital Pins)
#define DIO1 22
#define CLK1 23
#define DIO2 26
#define CLK2 27
#define DIO3 24
#define CLK3 25
#define DIO4 28
#define CLK4 29
//declare 4 traffic lights
TrafficLight light_a(1, 90, CLK1, DIO1); // TrafficLight(dir, deafult sec, CLK, DIO)
TrafficLight light_b(1, 90, CLK2, DIO2);
TrafficLight light_c(2, 90, CLK3, DIO3);
TrafficLight light_d(2, 90, CLK4, DIO4);
int operand;
float second;
int nowDirect; // 1->ab; 2->cd;
int lastUpdate;
const long interval = 1000;
String received;
String message;
boolean NODEMCU_DISCONNECT = 1;
Timer sendESP;
StaticJsonDocument<1024> data;
StaticJsonDocument<1024> esp_data;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // 設定 LCD I2C 位址
void setup() {
//初始化序列埠
initSerial();
//初始化 lcd
initLCD();
// 等待 nodemcu
waitNodeMCU();
//等待 arduino led controller
waitLightController();
//設定初始秒數 (皆為 a 的初始秒數)
//設定初始紅燈方向為 1<--->2 (1)
// (direct, second)
setDirAndSec(1, light_a.defaultSec + 1);
//每 3 秒傳送秒數資料給 NodeMCU
sendESP.every(2000, sendJSON);
}
void loop() {
//秒數扣1
minus();
//判斷是否需要切換方向
checkSwitch();
//顯示秒數 (紅燈方向才顯示)
showSecond();
//把當前秒數, 當前方向 放到 data 字典檔裡面
data["now_second"] = light_a.nowSec;
data["now_direct"] = nowDirect;
// 傳送資料到 NodeMCU
sendESP.update();
// 監聽 NodeMCU 的訊息 (秒數變動)
listenToNodeMCU();
//延遲一秒
delay(1000);
}
void initSerial() {
Serial.begin(9600); //usb slot
Serial1.begin(9600); //for TX/RX message on arduino 2 (light controller)
Serial2.begin(9600); // for Transmit seconds to NodeMCU(TX only)
Serial3.begin(9600); //for Receive data from NodeMCU(RX only)
Serial.println("hi");
}
void initLCD() {
lcd.begin(16, 2); // 初始化 LCD,一行 16 的字元,共 2 行,預設開啟背光
lcd.clear();
}
void waitNodeMCU() {
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("Waiting for");
lcd.setCursor(0, 1); // 設定游標位置在第二行行首
lcd.print("NodeMCU WIFI..");
delay(1000);
//busy wait..
while (NODEMCU_DISCONNECT) {
if (Serial3.available() > 0) {
if (Serial3.read() == 100) {
NODEMCU_DISCONNECT = 0;
}
}
}
//Connected!
lcd.clear();
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("WIFI Connected!");
delay(1000);
}
void waitLightController() {
// 等待 Light Controller
lcd.setCursor(0, 0);
lcd.print("Waiting for");
lcd.setCursor(0, 1);
lcd.print("Light Controller");
delay(1000);
//busy wait..
while (Serial1.available() == 0) {}
lcd.clear();
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("Connected!");
delay(1000);
//lcd 顯示號誌初始狀態
lcd.clear();
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("Red: 1-2");
lcd.setCursor(0, 1); // 設定游標位置在第一行行首
lcd.print("Status: Normal");
}
void setDirAndSec(int direct, int sec) {
//告知切換方向
nowDirect = direct;
Serial1.print(nowDirect);
//設定秒數
light_a.init(sec);
light_b.init(sec);
light_c.init(sec);
light_d.init(sec);
}
void sendJSON() {
serializeJsonPretty(data, Serial2);
if (nowDirect == 1) {
Serial1.print(nowDirect);
} else if (nowDirect == 2) {
Serial1.print(nowDirect);
}
lcd.setCursor(0, 1); // 設定游標位置在第一行行首
lcd.print("Status: Normal ");
}
void minus() {
//秒數扣1
light_a.minus(1);
light_b.minus(1);
light_c.minus(1);
light_d.minus(1);
}
void checkSwitch() {
//當秒數為 0 時, 變更方向
if (light_a.nowSec <= 0 || light_c.nowSec <= 0) {
lcd.setCursor(0, 1); // 設定游標位置在第一行行首
//如果 1 <---> 2 方向是紅燈
if (nowDirect == 1) {
//變更方向為 3 <----> 4
nowDirect = 2;
Serial1.print(nowDirect);
light_a.setSec(light_c.variaSec);
light_b.setSec(light_c.variaSec);
light_c.setSec(light_c.variaSec);
light_d.setSec(light_c.variaSec);
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("Red: 3-4");
} else { //如果 3 <---> 4 方向是紅燈
//變更方向為 1 <----> 2
nowDirect = 1;
Serial1.print(nowDirect);
light_a.setSec(light_a.variaSec);
light_b.setSec(light_a.variaSec);
light_c.setSec(light_a.variaSec);
light_d.setSec(light_a.variaSec);
lcd.setCursor(0, 0); // 設定游標位置在第一行行首
lcd.print("Red: 1-2");
}
}
}
void showSecond() {
if (nowDirect == 1) {
light_a.show();
light_b.show();
light_c.clear();
light_d.clear();
} else if (nowDirect == 2) {
light_c.show();
light_d.show();
light_a.clear();
light_b.clear();
}
}
void listenToNodeMCU() {
if (Serial3.available() > 0) {
//讀取訊息
received = Serial3.readString();
//訊息剖析 (Deserialize)
DeserializationError error = deserializeJson(esp_data, received);
if (error) {
switch (error.code()) {
case DeserializationError::Ok:
Serial.print(F("Deserialization succeeded"));
break;
case DeserializationError::InvalidInput:
Serial.print(F("Invalid input!"));
break;
case DeserializationError::NoMemory:
Serial.print(F("Not enough memory"));
break;
default:
Serial.print(F("Deserialization failed"));
break;
}
} else {
//訊息萃取 (To integer)
second = esp_data["second"];
operand = esp_data["operand"];
//調整秒數 (switch case)
adjustSecond(second, operand);
//lcd print message
lcd.setCursor(0, 1);
lcd.print(message);
}
}
}
void adjustSecond(float sec, int oper) {
//調整秒數 1->"+"; 2->"-"; 3->"*"; 4->"/"; 5->"="
Serial.print("adjust second:");
Serial.println(sec);
Serial.print("operand:");
Serial.print(oper);
switch (oper) {
case 1: //"+"
message = "Add ";
light_a.add(int(sec));
light_b.add(int(sec));
light_c.add(int(sec));
light_d.add(int(sec));
break;
case 2: //"-"
message = "Minus ";
if ((light_c.nowSec - sec ) <= 0) {
light_a.nowSec = 0;
light_b.nowSec = 0;
light_c.nowSec = 0;
light_d.nowSec = 0;
} else {
light_a.minus(int(sec));
light_b.minus(int(sec));
light_c.minus(int(sec));
light_d.minus(int(sec));
}
break;
case 3: //"*"
message = "Mutiply ";
light_a.multiply(sec);
light_b.multiply(sec);
light_c.multiply(sec);
light_d.multiply(sec);
break;
case 4: //"/"
message = "Divide ";
light_a.divide(sec);
light_b.divide(sec);
light_c.divide(sec);
light_d.divide(sec);
break;
case 5: //"="
message = "Divide ";
light_a.setSec(int(sec));
light_b.setSec(int(sec));
light_c.setSec(int(sec));
light_d.setSec(int(sec));
break;
}
}
```
(2)control_led
```
#define RED1 22
#define GREEN1 23
#define RED2 26
#define GREEN2 27
#define RED3 24
#define GREEN3 25
#define RED4 28
#define GREEN4 29
String DIR1 = "49"; //ASCII -> 1
String DIR2 = "50"; //ASCII -> 2
String received;
void setup() {
initSerial();
initLight();
Serial1.write(100); //transmit init message to main controller
}
void loop() {
//listen to main controller
listenToMainController();
}
void initSerial() {
Serial.begin(9600);
Serial1.begin(9600);
}
void initLight() {
pinMode(RED1, OUTPUT);
pinMode(GREEN1, OUTPUT);
pinMode(RED2, OUTPUT);
pinMode(GREEN2, OUTPUT);
pinMode(RED3, OUTPUT);
pinMode(GREEN3, OUTPUT);
pinMode(RED4, OUTPUT);
pinMode(GREEN4, OUTPUT);
digitalWrite(RED1, HIGH);
digitalWrite(GREEN1, LOW);
digitalWrite(RED2, HIGH);
digitalWrite(GREEN2, LOW);
digitalWrite(RED3, LOW);
digitalWrite(GREEN3, HIGH);
digitalWrite(RED4, LOW);
digitalWrite(GREEN4, HIGH);
}
void listenToMainController() {
if (Serial1.available() > 0) {
received = Serial1.read();
Serial.println(received);
if (received == DIR1) {
digitalWrite(RED1, HIGH);
digitalWrite(GREEN1, LOW);
digitalWrite(RED2, HIGH);
digitalWrite(GREEN2, LOW);
digitalWrite(RED3, LOW);
digitalWrite(GREEN3, HIGH);
digitalWrite(RED4, LOW);
digitalWrite(GREEN4, HIGH);
} else if (received == DIR2) {
digitalWrite(RED1, LOW);
digitalWrite(GREEN1, HIGH);
digitalWrite(RED2, LOW);
digitalWrite(GREEN2, HIGH);
digitalWrite(RED3, HIGH);
digitalWrite(GREEN3, LOW);
digitalWrite(RED4, HIGH);
digitalWrite(GREEN4, LOW);
}
}
}
```
NodeMCU
```
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
const char* ssid = "ASUS_Aaron_2G";
const char* password = "0981429828";
WiFiServer wifiServer(2345);
ESP8266WebServer server(80);
HTTPClient http;
StaticJsonDocument<200> doc;
StaticJsonDocument<200> doc1;
JsonObject data = doc1.to<JsonObject>();
String received = "";
String url = "";
String page, page2, page3;
int now;
int past;
int httpCode;
int value;
int sending;
String second, operand;
long now_direct, now_second;
void setup() {
initSerial();
//waiting for wifi connection
initWIFI();
//start wifi server
initWIFIServer();
//send init message to main controller
Serial1.write(100);
}
void loop() {
listenToMainController();
server.handleClient();
}
void listenToMainController() {
while (Serial.available() > 0) {
received = Serial.readString();
Serial.println(received);
DeserializationError error = deserializeJson(doc, received);
JsonObject data = doc.as<JsonObject>();
now_second = data["now_second"];
now_direct = data["now_direct"];
passInfo(now_direct, now_second);
}
}
void initSerial() {
Serial.begin(9600); // for receiving seconds from Arduino
Serial1.begin(9600);// for transmitting operator and operands //D4
}
void initWIFI() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.println("Connecting...");
delay(1000);
}
Serial.print("Conntected to Wifi. IP:");
Serial.println(WiFi.localIP());
wifiServer.begin();
Serial.println("port 2345 opened");
Serial.println(WiFi.macAddress());
}
void initWIFIServer() {
//page info
page = "<h1>NodeMCU Web Server</h1>";
server.on("/", []() {
server.send(200, "text/html", page);
});
server.on("/change", []() {
operand = server.arg(0);
second = server.arg(1);
page2 = "<h1>Operand:" + operand;
page2 += "</h1><h1><p>Data:";
page2 += second;
page2 += "</p></h1>";
server.send(200, "text/html", page2);
data["operand"] = operand;
data["second"] = second;
Serial.print("operand:");
Serial.print(operand);
Serial.println("second:");
Serial.print(second);
//send message to Arduino
serializeJsonPretty(data, Serial1);
});
server.begin();
}
void passInfo(int dir, int sec) {
url = "http://192.168.50.46/arduino/" + String(dir) + "/" + String(sec);
http.begin(url);
httpCode = http.GET();
http.end();
}
```
Custom Library
(1)TrafficLight.h
```
#define TrafficLight_h
#include "TM1637Display.h"
class TrafficLight
{
public:
TrafficLight(int dir, int sec, int CLK, int DIO);
void init(int sec);
void show();
void add(int sec);
void minus(int sec);
void multiply(float sec);
void divide(float sec);
void setSec(int sec);
void changeVariaSec(int sec);
void clear();
int direction;
int defaultSec;
int nowSec;
int variaSec;
TM1637Display TM1637;
};
```
(2)TrafficLight.cpp
```
#include "TrafficLight.h"
TrafficLight::TrafficLight(int dir, int sec, int CLK, int DIO):TM1637(CLK, DIO)
{
direction = dir;
defaultSec = sec;
variaSec = sec;
}
void TrafficLight::init(int sec){
TM1637.setBrightness(0x0f);
nowSec = sec;
TM1637.showNumberDec(sec);
}
void TrafficLight::show(){
TM1637.showNumberDec(nowSec);
}
void TrafficLight::setSec(int sec){
nowSec = sec;
}
void TrafficLight::add(int sec){
nowSec += sec;
}
void TrafficLight::minus(int sec){
nowSec -= sec;
}
void TrafficLight::multiply(float sec){
float temp = nowSec * sec;
nowSec = int(temp);
}
void TrafficLight::divide(float sec){
float temp = nowSec / sec;
nowSec = int(temp);
}
void TrafficLight::changeVariaSec(int sec){
variaSec -= sec;
}
void TrafficLight::clear(){
TM1637.clear();
}
```
Raspberry Pi Camera Server
(1)app.py
```
#!/usr/bin/env python
from importlib import import_module
import os
from flask import Flask, render_template, Response, request
from camera_opencv import Camera
app = Flask(__name__)
def gen2(camera):
"""Returns a single image frame"""
frame = camera.get_frame()
yield frame
@app.route('/image')
def image():
"""Returns a single current image for the webcam"""
cameraID = request.args.get('cid')
return Response(gen2(Camera()), mimetype='image/jpeg')
def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/stream')
def stream():
cameraID = request.args.get('cid')
#return Response(gen(VideoCamera(cameraID)), mimetype='multipart/x-mixed-replace; boundary=frame')
return Response(gen(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0', port='5000', threaded=True)
```
(2)base_camera.py
```
import time
import threading
try:
from greenlet import getcurrent as get_ident
except ImportError:
try:
from thread import get_ident
except ImportError:
from _thread import get_ident
class CameraEvent(object):
"""An Event-like class that signals all active clients when a new frame is
available.
"""
def __init__(self):
self.events = {}
def wait(self):
"""Invoked from each client's thread to wait for the next frame."""
ident = get_ident()
if ident not in self.events:
# this is a new client
# add an entry for it in the self.events dict
# each entry has two elements, a threading.Event() and a timestamp
self.events[ident] = [threading.Event(), time.time()]
return self.events[ident][0].wait()
def set(self):
"""Invoked by the camera thread when a new frame is available."""
now = time.time()
remove = None
for ident, event in self.events.items():
if not event[0].isSet():
# if this client's event is not set, then set it
# also update the last set timestamp to now
event[0].set()
event[1] = now
else:
# if the client's event is already set, it means the client
# did not process a previous frame
# if the event stays set for more than 5 seconds, then assume
# the client is gone and remove it
if now - event[1] > 5:
remove = ident
if remove:
del self.events[remove]
def clear(self):
"""Invoked from each client's thread after a frame was processed."""
self.events[get_ident()][0].clear()
class BaseCamera(object):
thread = None # background thread that reads frames from camera
frame = None # current frame is stored here by background thread
last_access = 0 # time of last client access to the camera
event = CameraEvent()
def __init__(self):
"""Start the background camera thread if it isn't running yet."""
if BaseCamera.thread is None:
BaseCamera.last_access = time.time()
# start background frame thread
BaseCamera.thread = threading.Thread(target=self._thread)
BaseCamera.thread.start()
# wait until frames are available
while self.get_frame() is None:
time.sleep(0)
def get_frame(self):
"""Return the current camera frame."""
BaseCamera.last_access = time.time()
# wait for a signal from the camera thread
BaseCamera.event.wait()
BaseCamera.event.clear()
return BaseCamera.frame
@staticmethod
def frames():
""""Generator that returns frames from the camera."""
raise RuntimeError('Must be implemented by subclasses.')
@classmethod
def _thread(cls):
"""Camera background thread."""
print('Starting camera thread.')
frames_iterator = cls.frames()
for frame in frames_iterator:
BaseCamera.frame = frame
BaseCamera.event.set() # send signal to clients
time.sleep(0)
# if there hasn't been any clients asking for frames in
# the last 10 seconds then stop the thread
if time.time() - BaseCamera.last_access > 10:
try:
frames_iterator.close()
print('Stopping camera thread due to inactivity.')
except GeneratorExit:
print("Generator Exit error")
finally:
print("finally")
break
BaseCamera.thread = None
```
(3)camera_opencv.py
```
import cv2
from base_camera import BaseCamera
class Camera(BaseCamera):
video_source = 0
@staticmethod
def set_video_source(source):
Camera.video_source = source
@staticmethod
def frames():
camera = cv2.VideoCapture(Camera.video_source)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
if not camera.isOpened():
raise RuntimeError('Could not start camera.')
while True:
# read current frame
_, img = camera.read()
# encode as a jpeg image and return it
try:
yield cv2.imencode('.jpg', img)[1].tobytes()
except GeneratorExit:
print("image encode error")
```
Python Task Server
```
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 29 13:29:40 2019
@author: chaos
"""
from darkflow.net.build import TFNet
import cv2
from io import BytesIO
import time
import requests
from PIL import Image, ImageDraw, ImageFont
import numpy as np
from time import gmtime, strftime
import threading
import queue
import pygame
import boto3
import json
import webbrowser
#darkflow
options = {"model": "cfg/yolo.cfg", "load": "bin/yolov2.weights", "threshold": 0.05}
tfnet = TFNet(options)
#line notify
_token = 'yourToken' #管理單位
token = 'yourAnotherToken' #維修單位
#laravel API
maintenance_url = 'http://127.0.0.1/api/maintenance/generate'
#sns
arnID='yourARNID'
count_dict = {"cam1":0, "cam2":0, "cam3":0, "cam4":0}
error_count_dict = {"cam1":0, "cam2":0, "cam3":0, "cam4":0}
#功能開關(default=False)
OPEN_NOTIFY = False
OPEN_RULE = False
#排程時間
timegap = 2
#記錄 物件辨識最後一次的執行時間
lastUpdated = int(round(time.time()))
#pygame 基本設定
pygame.init()
pygame.font.init()
screen = pygame.display.set_mode((1280, 870))
image = pygame.image.load('cars/error.jpg')
icon = pygame.image.load('images/icon.png')
waiting = pygame.image.load("images/waiting.png")
waiting = pygame.transform.scale(waiting, (400, 400))
warning = pygame.image.load("images/warning.png")
pygame.display.set_caption('監控台')
pygame.display.set_icon(icon)
#pygame 各鏡頭圖片位置
camPic_pos = {
1: [0, 150],
2: [640, 150],
3: [0, 510],
4: [640, 510]
}
#pygame 各鏡頭文字位置
camTitle_pos = {
1: [1, 160],
2: [650, 160],
3: [10, 520],
4: [650, 520]
}
cam_title = {
1: pygame.image.load('images/cam1_title.png'),
2: pygame.image.load('images/cam2_title.png'),
3: pygame.image.load('images/cam3_title.png'),
4: pygame.image.load('images/cam4_title.png')
}
#初始畫面
icon_color = pygame.image.load('images/icon_color.png')
icon = pygame.transform.scale(icon_color, (300, 300))
screen.blit(icon, (160, 230))
#pygame 文字位置
font_title = pygame.font.Font('fonts/NotoSansCJKtc-Regular.otf', 40)
font_init_message = pygame.font.Font('fonts/NotoSansCJKtc-Regular.otf',80)
#起始訊息
init_message = font_init_message.render("監控系統啟動中", True, (255, 255, 255))
screen.blit(init_message, (450, 350))
#地址
district = font_title.render("新北市 新莊區", True, (255, 255, 0))
street = font_title.render("中正路/建國一路 交叉口", True, (0, 255, 0))
screen.blit(district, (10, 10))
screen.blit(street, (10, 70))
#模式
rule_status_title = font_title.render("號誌控制模式: ", True, (255, 255, 255))
rule_status = font_title.render("手動", True, (255, 0, 0))
screen.blit(rule_status_title, (840, 10))
screen.blit(rule_status, (1100, 10))
#推播
notify_status_title = font_title.render("推播功能: ", True, (255, 255, 255))
notify_status = font_title.render("關閉", True, (255, 0, 0))
screen.blit(notify_status_title, (920, 70))
screen.blit(notify_status, (1100, 70))
#更新畫面
pygame.display.update()
#PIL draw on picture
pilFont = ImageFont.truetype("fonts/NotoSansCJKtc-Regular.otf", 40)
def pygame_event():
global OPEN_NOTIFY
global OPEN_RULE
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
#符合點擊區域
if (pos[0] > 1100 and pos[0] < 1200):
#規則
if (pos[1] > 0 and pos[1] < 60):
screen.fill(pygame.Color("black"), (1100, 0, 1500, 65))
if (OPEN_RULE == True):
OPEN_RULE = False
rule_status = font_title.render("手動", True, (255, 0, 0))
screen.blit(rule_status, (1100, 10))
print("close rule")
else:
OPEN_RULE = True
rule_status = font_title.render("自動", True, (255, 255, 0))
screen.blit(rule_status, (1100, 10))
print("open rule")
return True
#通知
elif (pos[1] > 60 and pos[1] < 120):
screen.fill(pygame.Color("black"), (1100, 70, 1500, 120))
if (OPEN_NOTIFY == True):
OPEN_NOTIFY = False
notify_status = font_title.render("關閉", True, (255, 0, 0))
screen.blit(notify_status, (1100, 70))
print("close notify")
else:
OPEN_NOTIFY = True
notify_status = font_title.render("開啟", True, (255, 255, 0))
screen.blit(notify_status, (1100, 70))
print("open notify")
return True
return False
def sns(message):
print("發sns")
print(message)
print(type(message))
sns = boto3.client(
'sns',
aws_access_key_id="yourAccessKey",
aws_secret_access_key="yourSecretAccessKey",
aws_session_token='yourToken',
region_name='yourRegion',
)
sns.publish(
TopicArn='yourARNTopic',
Message = message
)
return None
def lineNotify(token, msg, camID):
headers = {
"Authorization": "Bearer " + token,
}
payload = {'message': msg}
if (camID == 0):
try:
session = requests.Session()
r = session.post("https://notify-api.line.me/api/notify", headers = headers, params = payload, timeout=3)
print(r.status_code)
print("success(pure message)")
return None
except:
print("error(pure message)")
return None
url = "C:/Users/Darkflow/Desktop/darkflow/cars/cam"+str(camID)+".jpg"
imageFile = {'imageFile': open(url, 'rb')}
try:
session = requests.Session()
r = session.post("https://notify-api.line.me/api/notify", headers = headers, params = payload, files=imageFile, timeout=3)
return r.content
except:
return None
def isHardwareAlive():
try:
get_second = requests.get("http://192.168.50.126/", timeout=3)
print("hardware health")
return True
except:
print('Hardware Failed')
return False
def hardwareHealthCheck():
#硬體無回應
if not isHardwareAlive():
if (OPEN_NOTIFY):
#laravel 產生維修單
try:
headers = {'authorization': "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjFcL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE1NTgzNDk5MTcsImV4cCI6MTU2Njk4OTkxNywibmJmIjoxNTU4MzQ5OTE3LCJqdGkiOiIxUlNTUlEwU0xDTFhHbEVGIiwic3ViIjoxLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Q42vS5ZghcT4uRAFccoQIZfBWHBBx8vLJ-BjYkuQDQY"}
payload = {'intersections_id': 1, 'content': '[A01]硬體控制器異常'}
maintenance = requests.post(maintenance_url, headers = headers, params=payload)
response_data = json.loads(maintenance.text)
#代表維修單正常生成,未重複
if (response_data["notify"] == 1):
#發sns
try:
sns("[A01]硬體控制器異常")
except:
print("sns error(hardware)")
#發line notify
message = '錯誤事件:[A01]硬體控制器無回應'
print(lineNotify(token, message, 0))
except:
print('Laravel API Timeout(hardware maintenance)')
return None
def getCarCount(url, cam_id):
try:
r = requests.get(url, timeout=3)
except:
#計算錯誤次數
error_count_dict["cam"+str(cam_id)] += 1
#鏡頭無回應
print("camID:", cam_id, " timeout.")
#錯誤次數達 3 次
if (error_count_dict["cam"+str(cam_id)] >= 4):
#顯示"warning"圖片
screen.blit(warning, camPic_pos[cam_id])
screen.blit(cam_title[cam_id], camTitle_pos[cam_id]) #顯示標題
pygame.display.flip()
#推播
if (OPEN_NOTIFY):
#laravel 產生維修單
try:
headers = {'authorization': "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMjcuMC4wLjFcL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE1NTgzNDk5MTcsImV4cCI6MTU2Njk4OTkxNywibmJmIjoxNTU4MzQ5OTE3LCJqdGkiOiIxUlNTUlEwU0xDTFhHbEVGIiwic3ViIjoxLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Q42vS5ZghcT4uRAFccoQIZfBWHBBx8vLJ-BjYkuQDQY"}
payload = {'intersections_id': 1, 'content': '[C01]鏡頭1無回應'}
url = "C:/Users/Darkflow/Desktop/darkflow/cars/cam"+str(cam_id)+".jpg"
imageFile = {'imageFile': open(url, 'rb')}
maintenance = requests.post(maintenance_url, headers = headers, params=payload, files = imageFile)
response_data = json.loads(maintenance.text)
#代表維修單正常生成,未重複
if (response_data["notify"] == 1):
#發sns
try:
sns("[C01]鏡頭1無回應")
except:
print("sns error")
#發line notify
message = '[C01]鏡頭1無回應'
print(lineNotify(token, message, cam_id))
except:
print('Laravel API Timeout(maintenance)')
#錯誤次數未達3次
elif (error_count_dict["cam"+str(cam_id)] == 2):
#顯示"waiting"圖片
screen.blit(waiting, camPic_pos[cam_id])
screen.blit(cam_title[cam_id], camTitle_pos[cam_id]) #顯示標題
pygame.display.flip()
return 0
#成功取得影像,刷新錯誤次數
error_count_dict["cam"+str(cam_id)] = 0
#影像處理
curr_img = Image.open(BytesIO(r.content))
curr_img_cv2 = cv2.cvtColor(np.array(curr_img), cv2.COLOR_RGB2BGR)
#辨識物體
result = tfnet.return_predict(curr_img_cv2)
#影像轉 PIL ImageDraw Object
draw = ImageDraw.Draw(curr_img)
#圈出物體位置
cars = drawCar(draw, result)
#保存畫完的圖片到 local
curr_img.save('cars/cam%d.jpg' %(cam_id))
#在pygame顯示圖片
image = pygame.image.load('cars/cam{}.jpg'.format(cam_id)) #讀取上一行保存的圖片
picture = pygame.transform.scale(image, (640, 360)) #調整圖片尺寸
screen.blit(picture, camPic_pos[cam_id]) #放到screen
screen.blit(cam_title[cam_id], camTitle_pos[cam_id]) #顯示標題
pygame.display.update() #更新畫面
message = "鏡頭"+str(cam_id)+"偵測到車輛:"+str(cars)+"台"
print("camera %d: %d cars detected"%(cam_id, cars))
#存入車輛數
count_dict["cam"+str(cam_id)] = cars
return None
def drawCar(image, result):
carsSeen = 0
for detection in result:
if detection['label'] == 'car' :
#curr_img.save('cars/%i.jpg' %calculator)
x_range = detection['bottomright']['x'] - detection['topleft']['x']
if (x_range < 300):
carsSeen += 1
if detection['label'] == 'car':
image.rectangle([detection['topleft']['x'], detection['topleft']['y'],
detection['bottomright']['x'], detection['bottomright']['y']],
outline=(99, 54, 254), width=5)
image.rectangle([detection['topleft']['x'], detection['topleft']['y'] - 42,
detection['topleft']['x'] + 80, detection['topleft']['y']],
fill=(99, 54, 254))
else: #motorbike
image.rectangle([detection['topleft']['x'], detection['topleft']['y'],
detection['bottomright']['x'], detection['bottomright']['y']],
outline=(255, 255, 0), width=5)
image.rectangle([detection['topleft']['x'], detection['topleft']['y'] - 42,
detection['topleft']['x'] + 200, detection['topleft']['y']],
fill=(255, 255, 0))
image.text((detection['topleft']['x'] + 8, detection['topleft']['y'] - 48), detection['label'], font=pilFont, fill=(0,0,0,255))
return carsSeen
def detectAndCount():
que = queue.Queue();
thread_list = list();
cam_1 = threading.Thread(target=lambda q, arg1, arg2: q.put(getCarCount(arg1, arg2)), args=(que, 'http://192.168.50.172:5000/image', 1))
cam_2 = threading.Thread(target=lambda q, arg1, arg2: q.put(getCarCount(arg1, arg2)), args=(que, 'http://192.168.50.172:5001/image', 2))
cam_3 = threading.Thread(target=lambda q, arg1, arg2: q.put(getCarCount(arg1, arg2)), args=(que, 'http://192.168.50.206:5002/image', 3))
cam_4 = threading.Thread(target=lambda q, arg1, arg2: q.put(getCarCount(arg1, arg2)), args=(que, 'http://192.168.50.206:5003/image', 4))
cam_1.start()
thread_list.append(cam_1);
cam_2.start()
thread_list.append(cam_2);
cam_3.start()
thread_list.append(cam_3);
cam_4.start()
thread_list.append(cam_4);
for t in thread_list:
t.join()
while que.qsize() != 4:
continue
que.get()
que.get()
que.get()
que.get()
print("cam1:", count_dict["cam1"])
print("cam2:", count_dict["cam2"])
print("cam3:", count_dict["cam3"])
print("cam4:", count_dict["cam4"])
return None
def judgeRule(isOPENRULE, l1_car, l2_car, l3_car, l4_car):
if isOPENRULE:
judgeURL = "http://127.0.0.1/judgeRule/1/{light1}/{light2}/{light3}/{light4}/1".format(light1=l1_car, light2=l2_car, light3=l3_car, light4=l4_car)
# lineNotify(_token, '中正路/建國一路交叉口 已套用規則', 0)
else:
judgeURL = "http://127.0.0.1/judgeRule/1/{light1}/{light2}/{light3}/{light4}/0".format(light1=l1_car, light2=l2_car, light3=l3_car, light4=l4_car)
try:
currentRule = requests.get(judgeURL, timeout=2)
result = "Rule Judge: {id}".format(id=currentRule.content)
print(result)
return result
except:
err = "Laravel API Timeout(judge rule)"
print(err)
return err
def main():
global lastUpdated
global timegap
while True:
#如果pygame發生事件
if pygame_event():
#更新畫面
pygame.display.flip()
#執行排程任務
if (int(round(time.time())) - lastUpdated > timegap):
#辨識車輛數
detectAndCount()
#規則比較
judge = threading.Thread(target = judgeRule, args=[OPEN_RULE, count_dict["cam1"], count_dict["cam2"], count_dict["cam3"], count_dict["cam4"]])
judge.start()
#重置計時器
lastUpdated = int(round(time.time()))
#硬體健康檢測
hardwareHealthCheck()
if __name__ == '__main__':
main()
```