Spaces:
Runtime error
Runtime error
| 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 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: | |
| 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 | |
| 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() | |
| def thread(n): | |
| global users | |
| global conn | |
| global projectid | |
| global endpoint | |
| 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 = None | |
| respond = Responder(projectid, n, acceptstaticpayload, acceptstreamingpayload, value, user) | |
| endpoint[reqendpoint].receivedMessage(payload, user, respond) | |
| def start_server(endpoints): | |
| global conn | |
| global endpoint | |
| endpoints.insert(0, ConnectionEndpoint()) | |
| endpoint = endpoints | |
| conn = session.connect_cloud(project_id) | |
| threads = [threading.Thread(target=thread, args=(i+1,)) for i in range(10)] | |
| for t in threads: | |
| t.start() | |
| return t |