Spaces:
Running
Running
File size: 5,981 Bytes
d8d884a 4dd11c7 d8d884a 3645afb 4dd11c7 d8d884a 4dd11c7 d8d884a 4dd11c7 d8d884a 6eb30cb d8d884a 4dd11c7 d8d884a 4dd11c7 d8d884a 748b6e4 d8d884a 57bb78a d8d884a 3645afb d8d884a 3645afb d8d884a 6eb30cb 4dd11c7 3645afb 53ee67d d8d884a 90bfb6e 4ea9251 90bfb6e 4dd11c7 ea8167e d8d884a ea8167e d8d884a 90bfb6e 961b061 90bfb6e |
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 |
import coding
import scratchattach as scratch3
import threading
import time
import random
import os
global conn
global projectid
global endpoint
global users
projectid = os.getenv("ProjectID")
users = {}
session = scratch3.login(os.getenv("Username"), os.getenv("Password"))
class User:
def __init__(self, name, id):
self.last_request = time.time()
self.name = name
self.id = id
class UserStartup:
def __init__(self):
self.last_request = time.time()
class Responder:
def __init__(self, projectid, channel, can_respond, can_stream, value, user):
user.last_request = time.time()
self.user = user
self.projectid = projectid
self.can_respond = can_respond
self.can_stream = can_stream
self.channel = channel
self.cooldown = time.time()
self.wrote = False
self.last_value = value
def poll(self):
value = scratch3.get_var(self.projectid, "channel "+str(self.channel))
if value != self.last_value and value != None:
self.user.last_request = time.time()
self.last_value = value
binary = coding.decimal_to_binary(int(value))
if binary[1:3]=="01":
value = str(coding.binary_to_decimal(binary[3:]))
if binary[1:3]=="10":
value = str("true" if binary[3:] == 1 else "false")
if binary[1:3]=="11":
value = coding.convert_to_text(binary[3:])
return value
def close(self):
if self.can_stream or not self.can_respond:
while time.time() - self.cooldown < 0.5:
time.sleep(0.5 - (time.time() - self.cooldown))
conn.set_var("channel "+str(self.channel), "0")
else:
while str(scratch3.get_var(self.projectid, "channel "+str(self.channel))) !="0":
pass
def respond(self, response):
global conn
if self.wrote and not self.can_stream:
raise Exception("Can't stream to this as a response")
if not (self.can_respond or self.can_stream):
raise Exception("Can't respond to this")
while time.time() - self.cooldown < 0.5:
time.sleep(0.5 - (time.time() - self.cooldown))
if self.can_respond or self.can_stream:
payload = "1"
if type(response) is int:
payload+="01"+coding.decimal_to_binary(response)
elif type(response) is bool:
payload+="10"+"1" if response else "0"
elif type(response) is str:
payload+="11"+coding.convert_to_binary(response)
self.last_value = str(coding.binary_to_decimal(payload))
conn.set_var("channel "+str(self.channel), str(coding.binary_to_decimal(payload)))
t= time.time()
times=0.2
while scratch3.get_var(self.projectid, "channel "+str(self.channel)) !=str(coding.binary_to_decimal(payload)):
if time.time()-t>=times:
print("Message not sent, retrying")
times+=0.1
conn.set_var("channel "+str(self.channel), str(coding.binary_to_decimal(payload)))
t=time.time()
self.wrote = True
self.cooldown = time.time()
class ConnectionEndpoint:
def receivedMessage(self, message, user, responder):
global users
r=random.randrange(1, 2047)
while r in users:
r=random.randrange(1, 2047)
users[r] = User(message, r)
responder.respond(r)
responder.close()
class HeartbeatEndpoint:
def receivedMessage(self, message, user, responder):
responder.close()
def thread(n):
global users
global conn
global projectid
global endpoint
heartbeater = HeartbeatEndpoint()
conn.set_var("channel "+str(n), "0")
while True:
value = scratch3.get_var(projectid, "channel "+str(n))
if str(value) != "0" and value != None:
binary = coding.decimal_to_binary(int(value))
reqendpoint = coding.binary_to_decimal(binary[1:6])
header = coding.binary_to_decimal(binary[6:17])
staticpayload = binary[17] == '1'
streamingpayload = binary[18] == '1'
acceptstaticpayload = binary[19] == '1'
acceptstreamingpayload = binary[20] == '1'
payload = None
if staticpayload and not streamingpayload:
payloadformat = binary[21:23]
if payloadformat == "01":
payload = str(coding.binary_to_decimal(binary[23:]))
if payloadformat == "10":
payload = "true" if binary[23:]=='1' else "false"
if payloadformat == "11":
payload = coding.convert_to_text(binary[23:])
if header in users:
user = users[header]
else:
user = UserStartup()
respond = Responder(projectid, n, acceptstaticpayload, acceptstreamingpayload, value, user)
if reqendpoint == 31:
heartbeater.receivedMessage(payload, user, respond)
else:
try:
endpoint[reqendpoint].receivedMessage(payload, user, respond)
except:
pass
def monitor_users():
global users
while True:
time.sleep(1)
for k, v in users.items():
if time.time() - v.last_request >= 300:
del users[k]
def start_server(endpoints):
global projectid
global conn
global endpoint
endpoints.insert(0, ConnectionEndpoint())
endpoint = endpoints
conn = session.connect_cloud(projectid)
threads = [threading.Thread(target=thread, args=(i+1,)) for i in range(10)]
for t in threads:
t.start()
monitorusers = threading.Thread(target=monitor_users)
monitorusers.start()
|