forked from K-Francis-H/little-stars-hack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcamera_feed.py
201 lines (168 loc) · 5.6 KB
/
camera_feed.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
from PIL import Image, ImageTk
from tkinter import Tk, Canvas
from socket import *
from queue import Queue
import struct
import logging
import sys
import io
import time
import _thread
BROADCAST_IP = '255.255.255.255'
BROADCAST_PORT = 32108
HELLO_PORT = 32100
CAM_PORT = 8070
CAM_RDY_PORT = 8080
PPPP_MAGIC_NUMBER = 0xF1
MSG_HELLO= 0x00
MSG_HELLO_ACK= 0x01
MSG_HELLO_TO= 0x02
MSG_HELLO_TO_ACK= 0x03
MSG_QUERY_DID= 0x08
MSG_QUERY_DID_ACK= 0x09
MSG_DEV_LGN= 0x10
MSG_DEV_LGN_ACK= 0x11
MSG_DEV_LGN_CRC= 0x12
MSG_DEV_LGN_ACK_CRC= 0x13
MSG_DEV_LGN_KEY= 0x14
MSG_DEV_LGN_ACK_KEY= 0x15
MSG_DEV_ONLINE_REQ= 0x18
MSG_DEV_ONLINE_REQ_ACK= 0x19
MSG_P2P_REQ= 0x20
MSG_P2P_REQ_ACK= 0x21
MSG_LAN_SEARCH= 0x30 #sent without magic number
MSG_LAN_NOTIFY= 0x31 #immediately after, again no magic
MSG_LAN_NOTIFY_ACK= 0x32 #maybe 0x04 -> 0x32 (endianess is wrong in decrypted packet)
MSG_PUNCH_TO= 0x40
MSG_PUNCH_PKT= 0x41
MSG_PUNCH_PKT_EX= 0x41
MSG_P2P_RDY= 0x42
MSG_P2P_RDY_EX= 0x42
MSG_P2P_RDY_ACK= 0x43
MSG_RS_LGN= 0x60
MSG_RS_LGN_ACK= 0x61
MSG_RS_LGN1= 0x62
MSG_RS_LGN1_ACK= 0x63
MSG_LIST_REQ1= 0x67
MSG_LIST_REQ= 0x68
MSG_LIST_REQ_ACK= 0x69
MSG_RLY_HELLO= 0x70
MSG_RLY_HELLO_ACK= 0x71
MSG_RLY_PORT= 0x72
MSG_RLY_PORT_ACK= 0x73
MSG_RLY_PORT_KEY= 0x74
MSG_RLY_PORT_ACK_KEY= 0x75
MSG_RLY_BYTE_COUNT= 0x78
MSG_RLY_REQ= 0x80
MSG_RLY_REQ_ACK= 0x81
MSG_RLY_TO= 0x82
MSG_RLY_PKT= 0x83
MSG_RLY_RDY= 0x84
MSG_RLY_TO_ACK= 0x85
MSG_RLY_SERVER_REQ= 0x87
MSG_RLY_SERVER_REQ_ACK= 0x87
MSG_SDEV_RUN= 0x90
MSG_SDEV_LGN= 0x91
MSG_SDEV_LGN_ACK= 0x91
MSG_SDEV_LGN_CRC= 0x92
MSG_SDEV_LGN_ACK_CRC= 0x92
MSG_SDEV_REPORT= 0x94
MSG_CONNECT_REPORT= 0xA0
MSG_REPORT_REQ= 0xA1
MSG_REPORT= 0xA2
MSG_DRW= 0xD0
MSG_DRW_ACK= 0xD1
MSG_PSR= 0xD8
MSG_ALIVE= 0xE0
MSG_ALIVE_ACK= 0xE1
MSG_CLOSE= 0xF0
MSG_MGM_DUMP_LOGIN_DID= 0xF4
MSG_MGM_DUMP_LOGIN_DID_DETAIL= 0xF5
MSG_MGM_DUMP_LOGIN_DID_1= 0xF6
MSG_MGM_LOG_CONTROL= 0xF7
MSG_MGM_REMOTE_MANAGEMENT= 0xF8
HEADER_FMT = '>BB'
def network_loop():
global image_queue
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(('',0))
camera_initialized = initiate_camera(s)
if( not camera_initialized ):
print("Unable to initialize camera...")
print("Make sure your computer is connected to the camera's WiFi AP")
frame = bytearray()
while camera_initialized:
(buf, rinfo) = s.recvfrom(4096)
port = rinfo[1]
if(port == 8080):
#print("8080 packet")
if(packet_is_image_start(buf)):
frame = bytearray(buf)[8:]
else:
frame += bytearray(buf)[8:]
if(packet_is_image_end(buf)):
#create image and enqueue it
try:
raw_image = Image.open(io.BytesIO(bytes(frame[:])))
tk_image = ImageTk.PhotoImage(raw_image)
image_queue.put(tk_image, False)
except OSError as e:
print(e)
#elif(port == 8070):
#print("8070 packet")
def initiate_camera(sock):
#3 msgs, 6 bytes
msg1 = struct.pack(HEADER_FMT, MSG_LAN_SEARCH, 0x67)
msg2 = struct.pack(HEADER_FMT, MSG_LAN_SEARCH, 0x66)
msg_rdy = struct.pack(HEADER_FMT, MSG_P2P_RDY, 0x76)
size = sock.sendto(msg1, ('192.168.4.153', CAM_PORT))
size += sock.sendto(msg2, ('192.168.4.153', CAM_PORT))
size += sock.sendto(msg_rdy, ('192.168.4.153', CAM_RDY_PORT))
return (size == 6)
def packet_is_image_start(buf):
#may also want to look for the full JFIF header...
IMAGE_START = [0xff, 0xd8] #JFIF image start identifier
for i in range(0, len(buf)-1):
if(buf[i] == IMAGE_START[0] and buf[i+1] == IMAGE_START[1]):
return True
return False
def packet_is_image_end(buf):
IMAGE_END = [0xff, 0xd9]
for i in range(0, len(buf)-1):
if(buf[i] == IMAGE_END[0] and buf[i+1] == IMAGE_END[1]):
return True
return False
class IPCameraWindow():
def __init__(self, root, queue):
super().__init__()
self.queue = queue
root.wm_title("Little Stars Hack")
root.geometry("640x480")
self.canvas = Canvas(root, height=480, width=640)
self.canvas.pack()
tmp_img = Image.new('RGBA', (640,480), color=(0,0,255))
tmp_img_tk = ImageTk.PhotoImage(tmp_img)
self.image_container = self.canvas.create_image((0,0), anchor='nw', image=tmp_img_tk)
root.update()
root.after(1, self.update_canvas)
self.root = root
def update_canvas(self):
print("update_canvas")
print("queue size: "+str(self.queue.qsize()))
try:
img = self.queue.get(False)
self.canvas.itemconfig(self.image_container, image=img)
se;f.root.update() #this is intentional... it gives enough of a delay that the canvas updates
except Empty as e:
print("empty queue")
except Exception as e:
print(e)
finally:
self.root.after(100, self.update_canvas)
if __name__ == '__main__':
_thread.start_new_thread(network_loop, ())
root = Tk()
image_queue = Queue()
app = IPCameraWindow(root, image_queue)
root.mainloop()