Compare commits

...

2 commits
async ... main

Author SHA1 Message Date
Patrick
c26e0c18fb update for teams 2.0 2023-12-19 11:23:50 +01:00
4f10c493ac Merge pull request 'swap to async' (#1) from async into main
Reviewed-on: #1
2023-06-15 00:32:18 +02:00
2 changed files with 46 additions and 30 deletions

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "teams-ctrl"
version = "0.1.0"
version = "0.1.5"
description = "MS Teams control"
authors = ["Patrick Moessler <pub@asaril.de>"]
readme = "README.md"

View file

@ -6,8 +6,8 @@ import json
import time
import asyncio
from typing import Any
import serial_asyncio
from argparse import ArgumentParser
import serial_asyncio
from websockets.client import connect, WebSocketClientProtocol
from pydantic import BaseModel, ValidationError
@ -56,22 +56,26 @@ class MeetingPermissions(BaseModel):
class MeetingState(BaseModel):
isMuted: bool = False
isCameraOn: bool = False
isHandRaised: bool = False
isInMeeting: bool = False
isRecordingOn: bool = False
isBackgroundBlurred: bool = False
isSharing: bool = False
hasUnreadMessages: bool = False
isVideoOn: bool = False
class MeetingUpdate(BaseModel):
meetingState: MeetingState
meetingState: MeetingState | None
meetingPermissions: MeetingPermissions
class TeamsMsg(BaseModel):
apiVersion: str
meetingUpdate: MeetingUpdate
requestId: int | None
meetingUpdate: MeetingUpdate | None
tokenRefresh: str | None
errorMsg: str | None
response: str | None
class State:
@ -202,6 +206,8 @@ class TeamsCtrl:
self.meeting_state: MeetingState | None = None
self.request_id: int = 0
def set_next_state(self, next_state: str) -> None:
self.current_state_name = next_state
@ -239,6 +245,8 @@ class TeamsCtrl:
self.set_next_state(next_state=next_state)
async def send_ws_cmd(self, cmd: dict[str, Any]) -> None:
cmd.update({"requestId": self.request_id})
self.request_id += 1
msg = json.dumps(cmd)
await self.ws.send(msg)
@ -246,30 +254,38 @@ class TeamsCtrl:
async for raw_msg in self.ws:
try:
msg = TeamsMsg.parse_raw(raw_msg)
if self.meeting_state != msg.meetingUpdate.meetingState:
log.debug(
f"state changed:\n{self.meeting_state}\nto\n{msg.meetingUpdate.meetingState}"
)
changes: dict[str, bool] = {}
if self.meeting_state is None:
changes = msg.meetingUpdate.meetingState.dict()
else:
old_s = self.meeting_state.dict()
new_s = msg.meetingUpdate.meetingState.dict()
for state, old_v in old_s.items():
new_v = new_s[state]
if old_v != new_v:
changes[state] = new_v
next_state = self.current_state.handle_state_change(changes)
self.meeting_state = msg.meetingUpdate.meetingState
if next_state is not None:
self.set_next_state(next_state=next_state)
if (
msg.meetingUpdate is not None
and msg.meetingUpdate.meetingState is not None
):
if self.meeting_state != msg.meetingUpdate.meetingState:
log.debug(
f"state changed:\n{self.meeting_state}\nto\n{msg.meetingUpdate.meetingState}"
)
changes: dict[str, bool] = {}
if self.meeting_state is None:
changes = msg.meetingUpdate.meetingState.dict()
else:
old_s = self.meeting_state.dict()
new_s = msg.meetingUpdate.meetingState.dict()
for state, old_v in old_s.items():
new_v = new_s[state]
if old_v != new_v:
changes[state] = new_v
next_state = self.current_state.handle_state_change(changes)
self.meeting_state = msg.meetingUpdate.meetingState
if next_state is not None:
self.set_next_state(next_state=next_state)
elif msg.tokenRefresh is not None:
log.warning("got new token: %s" % msg.tokenRefresh)
else:
log.info(f"got valid but unhandled msg: {msg}")
except ValidationError:
if isinstance(raw_msg, bytes):
m = raw_msg.decode("utf-8")
else:
m = raw_msg
log.info(f"got unknown meetingState: {m}")
log.info(f"got unknown teams msg: {m}")
async def process_statemachine(self) -> None:
while not self.loop.is_closed():
@ -281,13 +297,13 @@ class TeamsCtrl:
)
async def amain() -> None:
async def amain(token: str, serial_port: str) -> None:
loop = asyncio.get_event_loop()
serial = await serial_asyncio.open_serial_connection(
loop=loop, url=args.port, baudrate=115200
loop=loop, url=serial_port, baudrate=115200
)
url = f"ws://localhost:8124?token={token}&protocol-version=1.0.0&manufacturer=TeamsCtrl&device=TeamsCtrl&app=TeamsCtrlApp&app-version=1.4"
url = f"ws://localhost:8124?token={token}&protocol-version=2.0.0&manufacturer=TeamsCtrl&device=TeamsCtrl&app=TeamsCtrlApp&app-version=1.5"
ws = await connect(url)
ctrl = TeamsCtrl(loop=loop, serial=serial, ws=ws)
@ -318,7 +334,7 @@ if __name__ == "__main__":
logging.getLogger("asyncio").setLevel(logging.INFO)
logging.getLogger("websockets.client").setLevel(logging.INFO)
with open(args.token) as tf:
with open(args.token, "r") as tf:
token = tf.read().strip()
asyncio.run(amain())
asyncio.run(amain(token, args.port))