- React App (For virtual students)
- Hand server
- Queue
- Tactile notifications
- Standalone Join
- Connecting raspberry pi to secure networks (like TMU)
- Auto wifi setup
Original app template: https://github.com/twilio/twilio-video-app-react#readme
-
Install dependencies:
npm install -
(Optional and probably not needed) Install noise cancellation:
npm run noisecancellation:krisp -
Install the CLI:
npm install -g twilio-clior use scoop on Windows -
Login:
twilio login -
Install the plugin for deploying the app (more info here):
twilio plugins:install plugin-rtc.
After following the steps below, run the app locally at http://localhost:3000 with
npm startIt's set up to use the twilio video go room type (2 participant max) when
running locally. Go rooms don't cost money so they can be used for development.
When the app is deployed, it uses group rooms.
https://www.twilio.com/docs/video/legacy-room-types
Copy the example
environment file to .env in the same directory and fill in the values below
- Open the Twilio Console.
- Click on 'Settings' and take note of your Account SID.
- Create a new API Key in the API Keys Section under Programmable Video Tools in the Twilio Console. Take note of the SID and Secret of the new API key.
- (This step is optional because plugin-rtc will
create a new conversation service called
${APP_NAME}-conversations-service. Make sure that both the react app .env and the standalone-join .env use the same conversation SID, otherwise they'll be in isolated chats) Create a new Conversations service in the Services section under the Conversations tab in the Twilio Console. Take note of the SID generated. - Store your Account SID, API Key SID, API Key Secret, and Conversations Service
SID in the
.envfile.
This might happen after deleting js files and then running vite dev or vite build? This error will show in your dev terminal running vite and also in the browser console as a "disallowed MIME type" error.
The file does not exist at "node_modules/.vite/deps/chunk-XXXXXXXX.js?v=XXXXXXXX"
which is in the optimize deps directory.
The dependency might be incompatible with the dep optimizer.
Try adding it to `optimizeDeps.exclude`.
Solution:
- Delete
node_modules - Clear browser cache
- Reinstall packages (
npm run i)
(more info at vitejs/vite#17738)
This error will show in the browser console and in an app popup. It happens when allowing media permissions in the prejoin screens. It might only happen on Chromium browsers and Windows.
Error Acquiring Media: NotReadableError Could not start video source
Scenario 1: When on Windows and the camera is already in use by some other app
Solution 1: Only allow permissions to the microphone and not the camera, or close the other app using the camera
Scenario 2: When minimum video constraints are too high for the computer visiting the website (like if the webcam is too low resolution)
Solution 2: Lower the minimum width and height in DEFAULT_VIDEO_CONSTRAINTS
Deploy the app: npm run deploy. The deployed app will use the group
room type instead of go.
See deployed app info (like url and expiration): npm run view
Undeploy the app: npm run delete
# run all jest tests
npm test
# run specific test (replace TEST_PATH with actual path of the test file)
# you can get the path by right clicking the file then "Copy Relative Path"
npm run test-specific TEST_PATH
# update test snapshot for a specific file
npm run update-snapshots:file TEST_PATHCypress needs these variables set in
Projects > PROJECT_NAME > Settings > Environment Variables
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_API_KEY_SID=SKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_API_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_CONVERSATIONS_SERVICE_SID=ISxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx# start cypress UI with vite dev server running
npm run cypress:devRun cypress tests:
- E2E Testing
- Choose any browser
- Click
twilio-video.cy.js
This runs on the raspberry pi (student-view only).
It's responsible for:
- Raising the hand on the raspberry pi
- Keeping the hand queue updated
- Live captions
- Tactile notifications (from the hand queue website)
- Ai schedules
- Text to speech
- Push to talk using livekit
- Hosting the website for hand queue and in person students
Setup virtual Python environment:
# create it in home dir
python -m venv ~/.hand-server-venv
# activate it
# (add this to ~/.bashrc for a shortcut)
# alias activatehs='source "$HOME/.hand-server-venv/bin/activate"'
source ~/.hand-server-venv/bin/activate
# install requirements (in venv)
pip install -r ~/webmoti-react/hand/app/requirements.txtNote: You need to activate the venv when running the hand server or changing packages
You can also activate it by typing activatehs (this is setup in .bashrc)
Next, copy the example
environment file to .env in the same directory and fill in the values
Vapid key pairs (for tactile push notifications) can be generated using
npx web-push generate-vapid-keys.
The hand server is exposed to the internet using remote.it. This needs to be setup on the raspberry pi running the hand server.
Setup: https://www.remote.it/getting-started/raspberry-pi
- Sign into the Remote.It portal https://app.remote.it
- (Optional - If you already have a persistent link and service setup, then you can restore it and skip step 3 https://support.remote.it/hc/en-us/articles/15635680105229-Restore-A-Device)
- Click "+" (Add Device) and select "Raspberry Pi", copy the generated code and paste it into the SSH console of your Raspberry Pi
Then to setup the HTTP service:
- Create new HTTP service
- Set service URL to
http://localhost:8080 - Enable the
Persistent public urlswitch - Make sure the routing for the link on the board is
[WEBPAGE IP].com/raisehand
# activate venv
source ~/.hand-server-venv/bin/activate
# (or activatehs)
python ~webmoti-react/hand/app/main.pyFlags:
--build-only: Enable to run npm build and exit. (ex: main.py --build-only)
This flag is there because you need to build the app after making changes.
Alternatively, you can navigate to the directory and npm run build
First setup pm2
# install pm2 globally
npm install -g pm2
pm2 startup systemd
# then copy paste the outputted command into terminalThen make pm2 run the hand server
source ~/.hand-server-venv/bin/activate # or activatehs
pm2 start python ~/webmoti-react/hand/app/main.py --name hand_server
pm2 save# run all
pytest
# more detailed output
pytest -v
# run one
pytest hand/app/tests/TEST_FILE.py
# run specific test
pytest hand/app/tests/TEST_FILE.py::TEST_NAMEThe hand queue website is hosted from the hand server and is meant to be displayed on a tablet for the professor.
It gets real time updates from the hand server using server-sent events.
The notification button on the bottom left turns on push notifications from the hand server. This shouldn't be done on the tablet, but on a separate phone.
The tablet automatically opens the hand queue website and keeps its screen on using an Autohotkey script.
- Install AutoHotkey v2
- Open startup folder:
- Press
Win + R - Open
shell:startup
- Press
- Create a shortcut to the auto open script
- It will run on boot now. You can also double click the script to run it.
Tactile notifications are helpful for when the prof doesn't hear or see the hand raising.
To enable notifications, open the hand queue website on a phone and click the notification bell. You should receive a confirmation notification if it works properly.
This uses push notifications instead of local notifications so it will work even when the phone is asleep. This allows the prof to put their phone in their pocket and get notified whenever the hand raises.
Some phones like Samsung have very aggressive battery optimization and might stop push notifications when the phone is asleep. You can change some battery settings so this doesn't happen. (https://dontkillmyapp.com/)
Both raspberry pi boards automatically join the twilio room when they're booted using a js script (standalone-join/main.js).
(This is already setup)
# install node version manager
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash# switch to correct node version
nvm install 20.8.0
nvm use 20.8.0
# check versions
node -v
npm -vInstalling puppeteer on raspberry pi (arm64) is broken. It doesn't install
the proper chromium binary. To fix this, use executablePath: /usr/bin/chromium-browser
when starting puppeteer. (This is already in the script)
(on raspberry pi)
cd webmoti-react/standalone-joinnpm install
Copy the example
environment file to .env in the same directory and fill in the values
Note: If autojoin.js is not launching when rasp pi is in headless mode then you need to download xvfb for running a virtual display and then instead of pm2 start autojoin.js, run pm2 start launch-autojoin.sh.
Command: sudo apt install xvfb
xvfb might also need to be set to run on boot. (Check pm2 logs first to see if this is the case)
pm2 start autojoin.js
pm2 saveYou can join the network like you would on a linux computer. Click the network icon in the top right of the Raspberry Pi desktop.
If you don't want to use your actual account, you can create a guest account: https://www.torontomu.ca/ccs/services/accounts/guestaccount/
Settings:
Wireless
SSID: TMU
Wireless Security
Security: WPA & WPA2 Enterprise
Authentication: Protected EAP (PEAP)
CA certificate: https://ai-apps.torontomu.ca/ccssoftware/allryerson/wireless/ca-bundle.crt
Identity: TMU username
Password: TMU password
https://www.miskatonic.org/2019/04/24/networkingpi/
-
Add this to
/etc/wpa_supplicant/wpa_supplicant.confand fill in your user details. Either hash the password with MD4 and input it with thehash:prefix or input it in plaintext in quotes.network={ ssid="" priority=1 proto=RSN key_mgmt=WPA-EAP pairwise=CCMP auth_alg=OPEN eap=PEAP identity="" password=hash: phase1="peaplabel=0" phase2="auth=MSCHAPV2" } -
Add this to
/etc/network/interfaces. The sleep 5 is needed to avoid a race condition.auto lo iface lo inet loopback iface eth0 inet dhcp allow-hotplug wlan0 iface wlan0 inet dhcp pre-up sleep 5 pre-up wpa_supplicant -B -i wlan0 \ -c /etc/wpa_supplicant/wpa_supplicant.conf -D nl80211 post-down killall -q wpa_supplicant -
If you need to use VNC viewer with ethernet, make sure that ethernet has higher priority over wifi. If you don't do this, it will always connect to wifi and you'll need to know the ip address to use VNC viewer.
Add this to
/etc/dhcpcd.confinterface eth0 metric 202 interface wlan0 metric 300 -
Make sure NetworkManager is disabled on boot and dhcpcd is enabled
sudo systemctl disable NetworkManager
sudo systemctl stop NetworkManager
sudo systemctl enable dhcpcd
sudo systemctl start dhcpcdThis is a way for the raspberry pi boards to connect to a wifi network in headless mode. This is in case you need to bring the WebMoti system somewhere that isn't TMU. It works by putting the wifi connection information on a USB and then plugging it into the Raspberry Pi.
Note:
For this to work, the dhcpcd config needs to be setup (see above)
Create this file /etc/udev/rules.d/99-usb-autorun.rules.
This rule will trigger the service below when a usb is plugged in.
ACTION=="add", \
KERNEL=="sd[a-z][0-9]", \
SUBSYSTEM=="block", \
ENV{SYSTEMD_WANTS}="usb-auto-wifi.service"Then create # /etc/systemd/system/usb-auto-wifi.service.
Replace USERNAME with imdc1 or imdc2.
This service will run after the usb mounts.
Note: It won't run if you're plugging it in again after
successfully connecting to wifi the first time
[Unit]
Description=Run script after USB is mounted
After=media-USERNAME-Webmoti.mount
[Service]
ExecStart=/usr/bin/python3 /home/USERNAME/add_wifi.py
Type=forking
[Install]
WantedBy=multi-user.targetRun sudo systemctl enable usb-auto-wifi.service to enable the service.
- Get a USB drive and name it
Webmoti. - Create a file named
wifi.inion the USB and fill in the connection information. Make sure the extension isiniand nottxt. - Plug the USB into the raspberry pi.
- Wait for at least 1 minute for it to run.
- Unplug it and check the
wifi_debug.logfile on the USB to see if it worked. This file will be created by the raspberry pi.