velconnect v2 wow

dev
Anton Franzluebbers 2022-07-05 20:01:45 -04:00
parent 4502662a53
commit 5762013f03
7 changed files with 501 additions and 135 deletions

1
.gitignore vendored
View File

@ -11,4 +11,5 @@ discord_bot/graph.png
discord_bot/config.py
env_win/
velconnect.db
velconnect*.db
.idea/

View File

@ -14,7 +14,7 @@ namespace VELConnect
public class VELConnectManager : MonoBehaviour
{
public string velConnectUrl = "http://localhost";
public static VELConnectManager instance;
private static VELConnectManager instance;
public class State
{
@ -36,7 +36,8 @@ namespace VELConnect
/// </summary>
public string TryGetData(string key)
{
return data?.TryGetValue(key, out string val) == true ? val : null;
string val = null;
return data?.TryGetValue(key, out val) == true ? val : null;
}
}
@ -50,6 +51,15 @@ namespace VELConnect
public string last_modified;
public string last_accessed;
public Dictionary<string, string> data;
/// <summary>
/// Returns the value if it exists, otherwise null
/// </summary>
public string TryGetData(string key)
{
string val = null;
return data?.TryGetValue(key, out val) == true ? val : null;
}
}
public Device device;
@ -63,6 +73,25 @@ namespace VELConnect
public static Action<string, string> OnDeviceDataChanged;
public static Action<string, string> OnRoomDataChanged;
private static readonly Dictionary<string, List<CallbackListener>> deviceFieldCallbacks = new Dictionary<string, List<CallbackListener>>();
private static readonly Dictionary<string, List<CallbackListener>> deviceDataCallbacks = new Dictionary<string, List<CallbackListener>>();
private static readonly Dictionary<string, List<CallbackListener>> roomDataCallbacks = new Dictionary<string, List<CallbackListener>>();
private struct CallbackListener
{
/// <summary>
/// Used so that other objects don't have to remove listeners themselves
/// </summary>
public MonoBehaviour keepAliveObject;
public Action<string> callback;
/// <summary>
/// Sends the first state received from the network or the state at binding time
/// </summary>
public bool sendInitialState;
}
public static int PairingCode
{
get
@ -80,10 +109,10 @@ namespace VELConnect
{
get
{
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
#if UNITY_EDITOR
// allows running multiple builds on the same computer
// return SystemInfo.deviceUniqueIdentifier + Hash128.Compute(Application.dataPath);
return SystemInfo.deviceUniqueIdentifier + "_BUILD";
return SystemInfo.deviceUniqueIdentifier + "_EDITOR";
#else
return SystemInfo.deviceUniqueIdentifier;
#endif
@ -137,7 +166,7 @@ namespace VELConnect
{ "version", Application.version },
{ "platform", SystemInfo.operatingSystem },
};
PostRequestCallback(velConnectUrl + "/api/v2/update_user_count", JsonConvert.SerializeObject(postData));
PostRequestCallback(velConnectUrl + "/api/update_user_count", JsonConvert.SerializeObject(postData));
});
}
@ -147,11 +176,13 @@ namespace VELConnect
{
try
{
GetRequestCallback(velConnectUrl + "/api/v2/get_state/" + DeviceId, json =>
GetRequestCallback(velConnectUrl + "/api/v2/device/get_data/" + DeviceId, json =>
{
State state = JsonConvert.DeserializeObject<State>(json);
if (state == null) return;
bool isInitialState = false;
// first load stuff
if (lastState == null)
{
@ -164,8 +195,9 @@ namespace VELConnect
Debug.LogError(e);
}
lastState = state;
return;
isInitialState = true;
// lastState = state;
// return;
}
@ -176,52 +208,126 @@ namespace VELConnect
foreach (FieldInfo fieldInfo in fields)
{
string newValue = fieldInfo.GetValue(state.device) as string;
string oldValue = fieldInfo.GetValue(lastState.device) as string;
string oldValue = lastState != null ? fieldInfo.GetValue(lastState.device) as string : null;
if (newValue != oldValue)
{
try
{
OnDeviceFieldChanged?.Invoke(fieldInfo.Name, newValue);
if (!isInitialState) OnDeviceFieldChanged?.Invoke(fieldInfo.Name, newValue);
}
catch (Exception e)
{
Debug.LogError(e);
}
// send specific listeners data
if (deviceFieldCallbacks.ContainsKey(fieldInfo.Name))
{
// clear the list of old listeners
deviceFieldCallbacks[fieldInfo.Name].RemoveAll(e => e.keepAliveObject == null);
// send the callbacks
deviceFieldCallbacks[fieldInfo.Name].ForEach(e =>
{
if (!isInitialState || e.sendInitialState)
{
try
{
e.callback(newValue);
}
catch (Exception ex)
{
Debug.LogError(ex);
}
}
});
}
}
}
if (state.device.data != null)
{
foreach (KeyValuePair<string, string> elem in state.device.data)
{
lastState.device.data.TryGetValue(elem.Key, out string oldValue);
string oldValue = null;
lastState?.device.data.TryGetValue(elem.Key, out oldValue);
if (elem.Value != oldValue)
{
try
{
OnDeviceDataChanged?.Invoke(elem.Key, elem.Value);
if (!isInitialState) OnDeviceDataChanged?.Invoke(elem.Key, elem.Value);
}
catch (Exception e)
catch (Exception ex)
{
Debug.LogError(e);
Debug.LogError(ex);
}
// send specific listeners data
if (deviceDataCallbacks.ContainsKey(elem.Key))
{
// clear the list of old listeners
deviceDataCallbacks[elem.Key].RemoveAll(e => e.keepAliveObject == null);
// send the callbacks
deviceDataCallbacks[elem.Key].ForEach(e =>
{
if (!isInitialState || e.sendInitialState)
{
try
{
e.callback(elem.Value);
}
catch (Exception ex)
{
Debug.LogError(ex);
}
}
});
}
}
}
}
}
if (state.room.modified_by != DeviceId)
if (state.room.modified_by != DeviceId && state.room.data != null)
{
foreach (KeyValuePair<string, string> elem in state.room.data)
{
lastState.room.data.TryGetValue(elem.Key, out string oldValue);
string oldValue = null;
lastState?.room.data.TryGetValue(elem.Key, out oldValue);
if (elem.Value != oldValue)
{
try
{
OnRoomDataChanged?.Invoke(elem.Key, elem.Value);
if (!isInitialState) OnRoomDataChanged?.Invoke(elem.Key, elem.Value);
}
catch (Exception e)
{
Debug.LogError(e);
}
// send specific listeners data
if (roomDataCallbacks.ContainsKey(elem.Key))
{
// clear the list of old listeners
roomDataCallbacks[elem.Key].RemoveAll(e => e.keepAliveObject == null);
// send the callbacks
roomDataCallbacks[elem.Key].ForEach(e =>
{
if (!isInitialState || e.sendInitialState)
{
try
{
e.callback(elem.Value);
}
catch (Exception ex)
{
Debug.LogError(ex);
}
}
});
}
}
}
}
@ -239,16 +345,130 @@ namespace VELConnect
}
}
/// <summary>
/// Adds a change listener callback to a particular field name within the Device main fields.
/// </summary>
public static void AddDeviceFieldListener(string key, MonoBehaviour keepAliveObject, Action<string> callback, bool sendInitialState = false)
{
if (!deviceFieldCallbacks.ContainsKey(key))
{
deviceFieldCallbacks[key] = new List<CallbackListener>();
}
deviceFieldCallbacks[key].Add(new CallbackListener()
{
keepAliveObject = keepAliveObject,
callback = callback,
sendInitialState = sendInitialState
});
if (sendInitialState)
{
if (instance != null && instance.lastState?.device != null)
{
if (instance.lastState.device.GetType().GetField(key)?.GetValue(instance.lastState.device) is string val)
{
try
{
callback(val);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
}
}
/// <summary>
/// Adds a change listener callback to a particular field name within the Device data JSON.
/// </summary>
public static void AddDeviceDataListener(string key, MonoBehaviour keepAliveObject, Action<string> callback, bool sendInitialState = false)
{
if (!deviceDataCallbacks.ContainsKey(key))
{
deviceDataCallbacks[key] = new List<CallbackListener>();
}
deviceDataCallbacks[key].Add(new CallbackListener()
{
keepAliveObject = keepAliveObject,
callback = callback,
sendInitialState = sendInitialState
});
if (sendInitialState)
{
string val = GetDeviceData(key);
if (val != null)
{
try
{
callback(val);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
}
/// <summary>
/// Adds a change listener callback to a particular field name within the Room data JSON.
/// </summary>
public static void AddRoomDataListener(string key, MonoBehaviour keepAliveObject, Action<string> callback, bool sendInitialState = false)
{
if (!roomDataCallbacks.ContainsKey(key))
{
roomDataCallbacks[key] = new List<CallbackListener>();
}
roomDataCallbacks[key].Add(new CallbackListener()
{
keepAliveObject = keepAliveObject,
callback = callback,
sendInitialState = sendInitialState
});
if (sendInitialState)
{
string val = GetRoomData(key);
if (val != null)
{
try
{
callback(val);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
}
public static string GetDeviceData(string key)
{
return instance != null ? instance.lastState?.device?.TryGetData(key) : null;
}
public static string GetRoomData(string key)
{
return instance != null ? instance.lastState?.room?.TryGetData(key) : null;
}
/// <summary>
/// Sets data on the device keys themselves
/// </summary>
public static void SetDeviceBaseData(Dictionary<string, object> data)
{
data["modified_by"] = DeviceId;
instance.PostRequestCallback(
instance.velConnectUrl + "/api/v2/device/set_data/" + DeviceId,
JsonConvert.SerializeObject(data)
JsonConvert.SerializeObject(data),
new Dictionary<string, string> { { "modified_by", DeviceId } }
);
}
@ -259,11 +479,8 @@ namespace VELConnect
{
instance.PostRequestCallback(
instance.velConnectUrl + "/api/v2/device/set_data/" + DeviceId,
JsonConvert.SerializeObject(new Dictionary<string, object>
{
{ "modified_by", DeviceId },
{ "data", data }
})
JsonConvert.SerializeObject(new Dictionary<string, object> { { "data", data } }),
new Dictionary<string, string> { { "modified_by", DeviceId } }
);
}
@ -275,10 +492,10 @@ namespace VELConnect
return;
}
data["modified_by"] = DeviceId;
instance.PostRequestCallback(
instance.velConnectUrl + "/api/v2/set_data/" + Application.productName + "_" + VelNetManager.Room,
JsonConvert.SerializeObject(data)
JsonConvert.SerializeObject(data),
new Dictionary<string, string> { { "modified_by", DeviceId } }
);
}
@ -308,13 +525,13 @@ namespace VELConnect
}
}
public void PostRequestCallback(string url, string postData, Action<string> successCallback = null,
public void PostRequestCallback(string url, string postData, Dictionary<string, string> headers = null, Action<string> successCallback = null,
Action<string> failureCallback = null)
{
StartCoroutine(PostRequestCallbackCo(url, postData, successCallback, failureCallback));
StartCoroutine(PostRequestCallbackCo(url, postData, headers, successCallback, failureCallback));
}
private static IEnumerator PostRequestCallbackCo(string url, string postData, Action<string> successCallback = null,
private static IEnumerator PostRequestCallbackCo(string url, string postData, Dictionary<string, string> headers = null, Action<string> successCallback = null,
Action<string> failureCallback = null)
{
UnityWebRequest webRequest = new UnityWebRequest(url, "POST");
@ -322,6 +539,14 @@ namespace VELConnect
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(bodyRaw);
webRequest.uploadHandler = uploadHandler;
webRequest.SetRequestHeader("Content-Type", "application/json");
if (headers != null)
{
foreach (KeyValuePair<string, string> keyValuePair in headers)
{
webRequest.SetRequestHeader(keyValuePair.Key, keyValuePair.Value);
}
}
yield return webRequest.SendWebRequest();
switch (webRequest.result)

View File

@ -24,6 +24,7 @@ class DB:
return conn, curr
def query(self, query_string: str, data: dict = None) -> list:
conn = None
try:
conn, curr = self.create_or_connect()
if data is not None:
@ -35,6 +36,7 @@ class DB:
return values
except:
print(traceback.print_exc())
if conn is not None:
conn.close()
raise

View File

@ -64,12 +64,12 @@ def get_device_by_pairing_code(pairing_code: str):
def create_device(hw_id: str):
db.insert("""
INSERT IGNORE INTO `Device`(hw_id) VALUES (:hw_id);
INSERT OR IGNORE INTO `Device`(hw_id) VALUES (:hw_id);
""", {'hw_id': hw_id})
@router.get('/device/get_data/{hw_id}')
def get_state(hw_id: str):
def get_state(request: fastapi.Request, hw_id: str):
"""Gets the device state"""
devices = db.query("""
@ -77,26 +77,35 @@ def get_state(hw_id: str):
""", {'hw_id': hw_id})
if len(devices) == 0:
return {'error': "Can't find device with that id."}
block = dict(devices[0])
if 'data' in block and block['data'] is not None:
block['data'] = json.loads(block['data'])
room_data = get_data(f"{devices[0]['current_app']}_{devices[0]['current_room']}")
room_key: str = f"{devices[0]['current_app']}_{devices[0]['current_room']}"
room_data = get_data(room_key)
return {'device': devices[0], 'room': room_data}
if "error" in room_data:
set_data(request, data={}, key=room_key, modified_by=None, category="room")
room_data = get_data(room_key)
return {'device': block, 'room': room_data}
@router.post('/device/set_data/{hw_id}')
def set_state(hw_id: str, data: dict, request: fastapi.Request):
def set_state(request: fastapi.Request, hw_id: str, data: dict, modified_by: str = None):
"""Sets the device state"""
create_device(hw_id)
# add the client's IP address if no sender specified
if 'modified_by' not in data:
data['modified_by'] = str(request.client) + "_" + str(request.headers)
if 'modified_by' in data:
modified_by = data['modified_by']
if modified_by is None:
modified_by: str = str(request.client) + "_" + str(request.headers)
allowed_keys: list[str] = [
'os_info',
'friendly_name',
'modified_by',
'current_app',
'current_room',
'pairing_code',
@ -107,15 +116,17 @@ def set_state(hw_id: str, data: dict, request: fastapi.Request):
db.insert(f"""
UPDATE `Device`
SET {key}=:value,
last_modified=CURRENT_TIMESTAMP
last_modified=CURRENT_TIMESTAMP,
modified_by=:modified_by
WHERE `hw_id`=:hw_id;
""",
{
'value': data[key],
'hw_id': hw_id,
'sender_id': data['sender_id']
'modified_by': modified_by
})
if key == "data":
new_data = data['data']
# get the old json values and merge the data
old_data_query = db.query("""
SELECT data
@ -124,8 +135,10 @@ def set_state(hw_id: str, data: dict, request: fastapi.Request):
""", {"hw_id": hw_id})
if len(old_data_query) == 1:
old_data: dict = json.loads(old_data_query[0]["data"])
data = {**old_data, **data}
old_data: dict = {}
if old_data_query[0]['data'] is not None:
old_data = json.loads(old_data_query[0]["data"])
new_data = {**old_data, **new_data}
# add the data to the db
db.insert("""
@ -133,7 +146,7 @@ def set_state(hw_id: str, data: dict, request: fastapi.Request):
SET data=:data,
last_modified=CURRENT_TIMESTAMP
WHERE hw_id=:hw_id;
""", {"hw_id": hw_id, "data": json.dumps(data)})
""", {"hw_id": hw_id, "data": json.dumps(new_data)})
return {'success': True}
@ -143,18 +156,22 @@ def generate_id(length: int = 4) -> str:
@router.post('/set_data')
def store_data_with_random_key(request: fastapi.Request, data: dict, category: str = None) -> dict:
def set_data_with_random_key(request: fastapi.Request, data: dict, modified_by: str = None,
category: str = None) -> dict:
"""Creates a little storage bucket for arbitrary data with a random key"""
return store_data(request, data, None, category)
return set_data(request, data, None, modified_by, category)
@router.post('/set_data/{key}')
def store_data(request: fastapi.Request, data: dict, key: str = None, modified_by: str = None, category: str = None) -> dict:
def set_data(request: fastapi.Request, data: dict, key: str = None, modified_by: str = None,
category: str = None) -> dict:
"""Creates a little storage bucket for arbitrary data"""
# add the client's IP address if no sender specified
if 'modified_by' in data:
modified_by = data['modified_by']
if modified_by is None:
modified_by = str(request.client) + "_" + str(request.headers)
modified_by: str = str(request.client) + "_" + str(request.headers)
# generates a key if none was supplied
if key is None:
@ -189,7 +206,7 @@ def get_data(key: str) -> dict:
"""Gets data from a storage bucket for arbitrary data"""
data = db.query("""
SELECT data
SELECT *
FROM `DataBlock`
WHERE id=:id
""", {"id": key})
@ -202,7 +219,11 @@ def get_data(key: str) -> dict:
try:
if len(data) == 1:
return json.loads(data[0])
block = dict(data[0])
if 'data' in block and block['data'] is not None:
block['data'] = json.loads(block['data'])
return block
return {'error': 'Not found'}
except:
except Exception as e:
print(e)
return {'error': 'Unknown. Maybe no data at this key.'}

View File

@ -18,8 +18,8 @@ function httpGetAsync(theUrl, callback, failCallback) {
function httpPostAsync(theUrl, data, callback, failCallback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
if (xmlHttp.readyState === 4) {
if (xmlHttp.status === 200) {
callback(xmlHttp.responseText);
} else {
failCallback(xmlHttp.status);

View File

@ -94,7 +94,7 @@
<div class="tile tile-centered col-6">
<div class="tile-content">
<div class="tile-title text-bold">Last Login</div>
<div class="tile-subtitle last_used">---</div>
<div class="tile-subtitle last_modified">---</div>
</div>
</div>
</div>
@ -167,6 +167,8 @@
<div class="tile-content">
<div class="tile-title text-bold">Current Room</div>
<input class="btn current_room" type="text" id="current_room" placeholder="----">
<input style="display: none;" class="btn current_app" type="text" id="current_app"
placeholder="----">
<button class="btn btn-primary btn-lg tooltip tooltip-right" id="set_room_id"
data-tooltip="Set Room ID">Set
</button>
@ -185,14 +187,36 @@
</div>
</div>
<br>
<div class="divider text-center" data-content="Screen Sharing"></div>
<div>
<p>To share your screen, download <a href="https://github.com/velaboratory/VEL-Share/releases/latest" target="_blank">VEL-Share
<div>
<div class="flex flex-col h-screen relative">
<header class="flex h-16 justify-center items-center text-xl bg-black text-white">
<div class="columns">
<button id="bnt_pubcam" class="btn btn-secondary btn-lg col-6"
onclick="start(true)">Publish Camera
</button>
<button id="bnt_pubscreen" class="btn btn-secondary btn-lg col-6"
onclick="start(false)">Publish Screen
</button>
</div>
</header>
<video style="width: 100%;" id="pub_video" class="bg-black" controls></video>
</div>
<script src="https://unpkg.com/ion-sdk-js@1.5.5/dist/ion-sdk.min.js"></script>
<script src="https://unpkg.com/ion-sdk-js@1.5.5/dist/json-rpc.min.js"></script>
</div>
<p>For more screen-sharing options and remote control, download <a
href="https://github.com/velaboratory/VEL-Share/releases/latest" target="_blank">VEL-Share
<svg style="width:1em;height:1em" viewBox="0 0 24 24">
<path fill="currentColor"
d="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z"/>
</svg>
</a></p>
</div>
<br>
</div>
</div>
@ -208,6 +232,7 @@
let headset_details = document.getElementById('headset_details');
let hw_id_field = document.getElementById('hw_id');
let failure = document.getElementById('failure');
let current_app = document.getElementById('current_app');
let current_room = document.getElementById('current_room');
let set_room_id = document.getElementById('set_room_id');
let set_user_color = document.getElementById('set_user_color');
@ -221,9 +246,10 @@
// check cookie
let hw_id = getCookie('hw_id');
if (hw_id !== "" && hw_id !== undefined && hw_id !== "undefined") {
httpGetAsync('/api/get_state/' + hw_id, (resp) => {
httpGetAsync('/api/v2/device/get_data/' + hw_id, (resp) => {
console.log(resp);
let respData = JSON.parse(resp);
@ -231,20 +257,17 @@
window.location.href = "/pair";
}
writeClass('hw_id', respData['user']['hw_id']);
writeClass('pairing_code', respData['user']['pairing_code']);
writeValue('current_room', respData['user']['current_room']);
writeClass('date_created', respData['user']['date_created'] + "<br>" + timeSinceString(respData['user']['date_created']) + " ago");
writeClass('last_used', respData['user']['last_used'] + "<br>" + timeSinceString(respData['user']['last_used']) + " ago");
writeValue('user_color', respData['user']['user_color']);
if (user_color) user_color.parentElement.style.color = "" + respData['user']['user_color'];
writeValue('user_name', respData['user']['user_name']);
writeValue('avatar_url', respData['user']['avatar_url']);
if (respData['room']) {
writeValue('tv_url', respData['room']['tv_url']);
writeValue('carpet_color', respData['room']['carpet_color']);
if (carpet_color) carpet_color.parentElement.style.color = "" + respData['room']['carpet_color'];
}
writeClass('hw_id', respData['device']['hw_id']);
writeClass('pairing_code', respData['device']['pairing_code']);
writeValue('current_app', respData['device']['current_app']);
writeValue('current_room', respData['device']['current_room']);
writeClass('date_created', respData['device']['date_created'] + "<br>" + timeSinceString(respData['device']['date_created']) + " ago");
writeClass('last_modified', respData['device']['last_modified'] + "<br>" + timeSinceString(respData['device']['last_modified']) + " ago");
writeValue('user_name', respData['device']['friendly_name']);
writeValue('avatar_url', respData['device']['data']?.['avatar_url']);
writeValue('tv_url', respData['room']?.['data']?.['tv_url']);
writeValue('carpet_color', respData['room']?.['data']?.['carpet_color']);
if (carpet_color) carpet_color.parentElement.style.color = "" + respData['room']?.['data']?.['carpet_color'];
Coloris({
@ -271,45 +294,61 @@
failure.style.display = "block";
});
function setUserData(data) {
data["sender_id"] = "web";
httpPostAsync('/api/set_headset_details/' + hw_id,
data,
(resp) => {
console.log('success');
function setDeviceField(data) {
fetch('/api/v2/device/set_data/' + hw_id, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
(status) => {
console.log('fail');
body: JSON.stringify(data)
})
.then(_ => console.log('success'))
.catch(_ => console.log('fail'));
}
);
function setDeviceData(data) {
fetch('/api/v2/device/set_data/' + hw_id, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"data": data})
})
.then(_ => console.log('success'))
.catch(_ => console.log('fail'));
}
function setRoomData(data) {
data["sender_id"] = "web";
httpPostAsync('/api/set_room_details/' + current_room.value,
data,
(resp) => {
console.log('success');
fetch('/api/v2/set_data/' + current_app.value + "_" + current_room.value, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
(status) => {
console.log('fail');
}
);
body: JSON.stringify(data)
})
.then(_ => console.log('success'))
.catch(_ => console.log('fail'));
}
if (set_room_id) {
set_room_id.addEventListener('click', () => {
setUserData({"current_room": current_room.value});
setDeviceField({"current_room": current_room.value});
});
}
if (set_user_color) {
set_user_color.addEventListener('click', () => {
setUserData({"user_color": document.getElementById('user_color').value});
setDeviceData({"user_color": document.getElementById('user_color').value});
});
}
if (set_user_name) {
set_user_name.addEventListener('click', () => {
setUserData({"user_name": document.getElementById('user_name').value});
setDeviceField({"friendly_name": document.getElementById('user_name').value});
});
}
if (set_tv_url) {
@ -324,7 +363,7 @@
}
if (set_avatar_url) {
set_avatar_url.addEventListener('click', () => {
setUserData({"avatar_url": document.getElementById('avatar_url').value});
setDeviceData({"avatar_url": document.getElementById('avatar_url').value});
});
}
@ -351,6 +390,84 @@
});
const roomName = (Math.random() + 1).toString(36).substring(7);
const pubVideo = document.getElementById("pub_video");
const subVideo = document.getElementById("sub_video");
const bntPubCam = document.getElementById("bnt_pubcam");
const bntPubScreen = document.getElementById("bnt_pubscreen");
setDeviceData({"streamer_stream_id": roomName});
const serverURL = "wss://velnet.ugavel.com/ws";
const config = {
iceServers: [
{
urls: "stun:stun.l.google.com:19302",
},
],
};
const signalLocal = new Signal.IonSFUJSONRPCSignal(serverURL);
const clientLocal = new IonSDK.Client(signalLocal, config);
signalLocal.onopen = () => clientLocal.join(roomName);
const start = (type) => {
if (type) {
IonSDK.LocalStream.getUserMedia({
resolution: "vga",
audio: true,
video: true,
codec: "vp8",
}).then((media) => {
pubVideo.srcObject = media;
pubVideo.autoplay = true;
pubVideo.controls = true;
pubVideo.muted = true;
bntPubCam.disabled = true;
bntPubScreen.disabled = true;
clientLocal.publish(media);
}).catch(console.error);
} else {
IonSDK.LocalStream.getDisplayMedia({
audio: true,
video: true,
codec: "vp8",
}).then((media) => {
pubVideo.srcObject = media;
pubVideo.autoplay = true;
pubVideo.controls = true;
pubVideo.muted = true;
bntPubCam.disabled = true;
bntPubScreen.disabled = true;
clientLocal.publish(media);
}).catch(console.error);
}
}
clientLocal.ontrack = (track, stream) => {
console.log("got track: ", track.id, "for stream: ", stream.id);
stream.mute();
stream.unmute();
if (track.kind === "video") {
subVideo.srcObject = stream;
subVideo.play();
}
//track.onunmute = () => {
//subVideo.srcObject = stream;
//subVideo.autoplay = true;
//subVideo.muted = true;
//subVideo.play();
//stream.onremovetrack = () => {
//subVideo.srcObject = null;
//}
//}
}
</script>
</div>
</body>

View File

@ -75,10 +75,10 @@
let submit_button = document.getElementById('submit_pairing_code');
let pair_code_input = document.getElementById('pair_code');
submit_button.addEventListener('click', () => {
httpGetAsync('/api/pair_headset/' + pair_code_input.value, (resp) => {
httpGetAsync('/api/v2/get_device_by_pairing_code/' + pair_code_input.value, (resp) => {
console.log(resp);
let respData = JSON.parse(resp);
if (respData['hw_id'] != '') {
if (respData['hw_id'] !== '') {
setCookie('hw_id', respData['hw_id'], 60);
window.location.href = "/";
}