velconnect v2 wow
parent
4502662a53
commit
5762013f03
|
|
@ -11,4 +11,5 @@ discord_bot/graph.png
|
||||||
discord_bot/config.py
|
discord_bot/config.py
|
||||||
env_win/
|
env_win/
|
||||||
velconnect.db
|
velconnect.db
|
||||||
|
velconnect*.db
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace VELConnect
|
||||||
public class VELConnectManager : MonoBehaviour
|
public class VELConnectManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
public string velConnectUrl = "http://localhost";
|
public string velConnectUrl = "http://localhost";
|
||||||
public static VELConnectManager instance;
|
private static VELConnectManager instance;
|
||||||
|
|
||||||
public class State
|
public class State
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +36,8 @@ namespace VELConnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TryGetData(string key)
|
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_modified;
|
||||||
public string last_accessed;
|
public string last_accessed;
|
||||||
public Dictionary<string, string> data;
|
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;
|
public Device device;
|
||||||
|
|
@ -63,6 +73,25 @@ namespace VELConnect
|
||||||
public static Action<string, string> OnDeviceDataChanged;
|
public static Action<string, string> OnDeviceDataChanged;
|
||||||
public static Action<string, string> OnRoomDataChanged;
|
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
|
public static int PairingCode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -80,10 +109,10 @@ namespace VELConnect
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
// allows running multiple builds on the same computer
|
// allows running multiple builds on the same computer
|
||||||
// return SystemInfo.deviceUniqueIdentifier + Hash128.Compute(Application.dataPath);
|
// return SystemInfo.deviceUniqueIdentifier + Hash128.Compute(Application.dataPath);
|
||||||
return SystemInfo.deviceUniqueIdentifier + "_BUILD";
|
return SystemInfo.deviceUniqueIdentifier + "_EDITOR";
|
||||||
#else
|
#else
|
||||||
return SystemInfo.deviceUniqueIdentifier;
|
return SystemInfo.deviceUniqueIdentifier;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -137,7 +166,7 @@ namespace VELConnect
|
||||||
{ "version", Application.version },
|
{ "version", Application.version },
|
||||||
{ "platform", SystemInfo.operatingSystem },
|
{ "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
|
try
|
||||||
{
|
{
|
||||||
GetRequestCallback(velConnectUrl + "/api/v2/get_state/" + DeviceId, json =>
|
GetRequestCallback(velConnectUrl + "/api/v2/device/get_data/" + DeviceId, json =>
|
||||||
{
|
{
|
||||||
State state = JsonConvert.DeserializeObject<State>(json);
|
State state = JsonConvert.DeserializeObject<State>(json);
|
||||||
if (state == null) return;
|
if (state == null) return;
|
||||||
|
|
||||||
|
bool isInitialState = false;
|
||||||
|
|
||||||
// first load stuff
|
// first load stuff
|
||||||
if (lastState == null)
|
if (lastState == null)
|
||||||
{
|
{
|
||||||
|
|
@ -164,8 +195,9 @@ namespace VELConnect
|
||||||
Debug.LogError(e);
|
Debug.LogError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastState = state;
|
isInitialState = true;
|
||||||
return;
|
// lastState = state;
|
||||||
|
// return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -176,52 +208,126 @@ namespace VELConnect
|
||||||
foreach (FieldInfo fieldInfo in fields)
|
foreach (FieldInfo fieldInfo in fields)
|
||||||
{
|
{
|
||||||
string newValue = fieldInfo.GetValue(state.device) as string;
|
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)
|
if (newValue != oldValue)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OnDeviceFieldChanged?.Invoke(fieldInfo.Name, newValue);
|
if (!isInitialState) OnDeviceFieldChanged?.Invoke(fieldInfo.Name, newValue);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> elem in state.device.data)
|
if (state.device.data != null)
|
||||||
{
|
{
|
||||||
lastState.device.data.TryGetValue(elem.Key, out string oldValue);
|
foreach (KeyValuePair<string, string> elem in state.device.data)
|
||||||
if (elem.Value != oldValue)
|
|
||||||
{
|
{
|
||||||
try
|
string oldValue = null;
|
||||||
|
lastState?.device.data.TryGetValue(elem.Key, out oldValue);
|
||||||
|
if (elem.Value != oldValue)
|
||||||
{
|
{
|
||||||
OnDeviceDataChanged?.Invoke(elem.Key, elem.Value);
|
try
|
||||||
}
|
{
|
||||||
catch (Exception e)
|
if (!isInitialState) OnDeviceDataChanged?.Invoke(elem.Key, elem.Value);
|
||||||
{
|
}
|
||||||
Debug.LogError(e);
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
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)
|
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)
|
if (elem.Value != oldValue)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OnRoomDataChanged?.Invoke(elem.Key, elem.Value);
|
if (!isInitialState) OnRoomDataChanged?.Invoke(elem.Key, elem.Value);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError(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>
|
/// <summary>
|
||||||
/// Sets data on the device keys themselves
|
/// Sets data on the device keys themselves
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SetDeviceBaseData(Dictionary<string, object> data)
|
public static void SetDeviceBaseData(Dictionary<string, object> data)
|
||||||
{
|
{
|
||||||
data["modified_by"] = DeviceId;
|
|
||||||
instance.PostRequestCallback(
|
instance.PostRequestCallback(
|
||||||
instance.velConnectUrl + "/api/v2/device/set_data/" + DeviceId,
|
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.PostRequestCallback(
|
||||||
instance.velConnectUrl + "/api/v2/device/set_data/" + DeviceId,
|
instance.velConnectUrl + "/api/v2/device/set_data/" + DeviceId,
|
||||||
JsonConvert.SerializeObject(new Dictionary<string, object>
|
JsonConvert.SerializeObject(new Dictionary<string, object> { { "data", data } }),
|
||||||
{
|
new Dictionary<string, string> { { "modified_by", DeviceId } }
|
||||||
{ "modified_by", DeviceId },
|
|
||||||
{ "data", data }
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,10 +492,10 @@ namespace VELConnect
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data["modified_by"] = DeviceId;
|
|
||||||
instance.PostRequestCallback(
|
instance.PostRequestCallback(
|
||||||
instance.velConnectUrl + "/api/v2/set_data/" + Application.productName + "_" + VelNetManager.Room,
|
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)
|
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)
|
Action<string> failureCallback = null)
|
||||||
{
|
{
|
||||||
UnityWebRequest webRequest = new UnityWebRequest(url, "POST");
|
UnityWebRequest webRequest = new UnityWebRequest(url, "POST");
|
||||||
|
|
@ -322,6 +539,14 @@ namespace VELConnect
|
||||||
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(bodyRaw);
|
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||||
webRequest.uploadHandler = uploadHandler;
|
webRequest.uploadHandler = uploadHandler;
|
||||||
webRequest.SetRequestHeader("Content-Type", "application/json");
|
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();
|
yield return webRequest.SendWebRequest();
|
||||||
|
|
||||||
switch (webRequest.result)
|
switch (webRequest.result)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ class DB:
|
||||||
return conn, curr
|
return conn, curr
|
||||||
|
|
||||||
def query(self, query_string: str, data: dict = None) -> list:
|
def query(self, query_string: str, data: dict = None) -> list:
|
||||||
|
conn = None
|
||||||
try:
|
try:
|
||||||
conn, curr = self.create_or_connect()
|
conn, curr = self.create_or_connect()
|
||||||
if data is not None:
|
if data is not None:
|
||||||
|
|
@ -35,7 +36,8 @@ class DB:
|
||||||
return values
|
return values
|
||||||
except:
|
except:
|
||||||
print(traceback.print_exc())
|
print(traceback.print_exc())
|
||||||
conn.close()
|
if conn is not None:
|
||||||
|
conn.close()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def insert(self, query_string: str, data: dict = None) -> bool:
|
def insert(self, query_string: str, data: dict = None) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,12 @@ def get_device_by_pairing_code(pairing_code: str):
|
||||||
|
|
||||||
def create_device(hw_id: str):
|
def create_device(hw_id: str):
|
||||||
db.insert("""
|
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})
|
""", {'hw_id': hw_id})
|
||||||
|
|
||||||
|
|
||||||
@router.get('/device/get_data/{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"""
|
"""Gets the device state"""
|
||||||
|
|
||||||
devices = db.query("""
|
devices = db.query("""
|
||||||
|
|
@ -77,26 +77,35 @@ def get_state(hw_id: str):
|
||||||
""", {'hw_id': hw_id})
|
""", {'hw_id': hw_id})
|
||||||
if len(devices) == 0:
|
if len(devices) == 0:
|
||||||
return {'error': "Can't find device with that id."}
|
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}')
|
@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"""
|
"""Sets the device state"""
|
||||||
|
|
||||||
create_device(hw_id)
|
create_device(hw_id)
|
||||||
|
|
||||||
# add the client's IP address if no sender specified
|
# add the client's IP address if no sender specified
|
||||||
if 'modified_by' not in data:
|
if 'modified_by' in data:
|
||||||
data['modified_by'] = str(request.client) + "_" + str(request.headers)
|
modified_by = data['modified_by']
|
||||||
|
if modified_by is None:
|
||||||
|
modified_by: str = str(request.client) + "_" + str(request.headers)
|
||||||
|
|
||||||
allowed_keys: list[str] = [
|
allowed_keys: list[str] = [
|
||||||
'os_info',
|
'os_info',
|
||||||
'friendly_name',
|
'friendly_name',
|
||||||
'modified_by',
|
|
||||||
'current_app',
|
'current_app',
|
||||||
'current_room',
|
'current_room',
|
||||||
'pairing_code',
|
'pairing_code',
|
||||||
|
|
@ -107,15 +116,17 @@ def set_state(hw_id: str, data: dict, request: fastapi.Request):
|
||||||
db.insert(f"""
|
db.insert(f"""
|
||||||
UPDATE `Device`
|
UPDATE `Device`
|
||||||
SET {key}=:value,
|
SET {key}=:value,
|
||||||
last_modified=CURRENT_TIMESTAMP
|
last_modified=CURRENT_TIMESTAMP,
|
||||||
|
modified_by=:modified_by
|
||||||
WHERE `hw_id`=:hw_id;
|
WHERE `hw_id`=:hw_id;
|
||||||
""",
|
""",
|
||||||
{
|
{
|
||||||
'value': data[key],
|
'value': data[key],
|
||||||
'hw_id': hw_id,
|
'hw_id': hw_id,
|
||||||
'sender_id': data['sender_id']
|
'modified_by': modified_by
|
||||||
})
|
})
|
||||||
if key == "data":
|
if key == "data":
|
||||||
|
new_data = data['data']
|
||||||
# get the old json values and merge the data
|
# get the old json values and merge the data
|
||||||
old_data_query = db.query("""
|
old_data_query = db.query("""
|
||||||
SELECT data
|
SELECT data
|
||||||
|
|
@ -124,8 +135,10 @@ def set_state(hw_id: str, data: dict, request: fastapi.Request):
|
||||||
""", {"hw_id": hw_id})
|
""", {"hw_id": hw_id})
|
||||||
|
|
||||||
if len(old_data_query) == 1:
|
if len(old_data_query) == 1:
|
||||||
old_data: dict = json.loads(old_data_query[0]["data"])
|
old_data: dict = {}
|
||||||
data = {**old_data, **data}
|
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
|
# add the data to the db
|
||||||
db.insert("""
|
db.insert("""
|
||||||
|
|
@ -133,7 +146,7 @@ def set_state(hw_id: str, data: dict, request: fastapi.Request):
|
||||||
SET data=:data,
|
SET data=:data,
|
||||||
last_modified=CURRENT_TIMESTAMP
|
last_modified=CURRENT_TIMESTAMP
|
||||||
WHERE hw_id=:hw_id;
|
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}
|
return {'success': True}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -143,18 +156,22 @@ def generate_id(length: int = 4) -> str:
|
||||||
|
|
||||||
|
|
||||||
@router.post('/set_data')
|
@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"""
|
"""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}')
|
@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"""
|
"""Creates a little storage bucket for arbitrary data"""
|
||||||
|
|
||||||
# add the client's IP address if no sender specified
|
# 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:
|
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
|
# generates a key if none was supplied
|
||||||
if key is None:
|
if key is None:
|
||||||
|
|
@ -189,7 +206,7 @@ def get_data(key: str) -> dict:
|
||||||
"""Gets data from a storage bucket for arbitrary data"""
|
"""Gets data from a storage bucket for arbitrary data"""
|
||||||
|
|
||||||
data = db.query("""
|
data = db.query("""
|
||||||
SELECT data
|
SELECT *
|
||||||
FROM `DataBlock`
|
FROM `DataBlock`
|
||||||
WHERE id=:id
|
WHERE id=:id
|
||||||
""", {"id": key})
|
""", {"id": key})
|
||||||
|
|
@ -202,7 +219,11 @@ def get_data(key: str) -> dict:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(data) == 1:
|
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'}
|
return {'error': 'Not found'}
|
||||||
except:
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
return {'error': 'Unknown. Maybe no data at this key.'}
|
return {'error': 'Unknown. Maybe no data at this key.'}
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ function httpGetAsync(theUrl, callback, failCallback) {
|
||||||
function httpPostAsync(theUrl, data, callback, failCallback) {
|
function httpPostAsync(theUrl, data, callback, failCallback) {
|
||||||
var xmlHttp = new XMLHttpRequest();
|
var xmlHttp = new XMLHttpRequest();
|
||||||
xmlHttp.onreadystatechange = function () {
|
xmlHttp.onreadystatechange = function () {
|
||||||
if (xmlHttp.readyState == 4) {
|
if (xmlHttp.readyState === 4) {
|
||||||
if (xmlHttp.status == 200) {
|
if (xmlHttp.status === 200) {
|
||||||
callback(xmlHttp.responseText);
|
callback(xmlHttp.responseText);
|
||||||
} else {
|
} else {
|
||||||
failCallback(xmlHttp.status);
|
failCallback(xmlHttp.status);
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
<div class="tile tile-centered col-6">
|
<div class="tile tile-centered col-6">
|
||||||
<div class="tile-content">
|
<div class="tile-content">
|
||||||
<div class="tile-title text-bold">Last Login</div>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -167,6 +167,8 @@
|
||||||
<div class="tile-content">
|
<div class="tile-content">
|
||||||
<div class="tile-title text-bold">Current Room</div>
|
<div class="tile-title text-bold">Current Room</div>
|
||||||
<input class="btn current_room" type="text" id="current_room" placeholder="----">
|
<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"
|
<button class="btn btn-primary btn-lg tooltip tooltip-right" id="set_room_id"
|
||||||
data-tooltip="Set Room ID">Set
|
data-tooltip="Set Room ID">Set
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -185,14 +187,36 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<div class="divider text-center" data-content="Screen Sharing"></div>
|
||||||
|
|
||||||
<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">
|
<svg style="width:1em;height:1em" viewBox="0 0 24 24">
|
||||||
<path fill="currentColor"
|
<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"/>
|
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>
|
</svg>
|
||||||
</a></p>
|
</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -208,6 +232,7 @@
|
||||||
let headset_details = document.getElementById('headset_details');
|
let headset_details = document.getElementById('headset_details');
|
||||||
let hw_id_field = document.getElementById('hw_id');
|
let hw_id_field = document.getElementById('hw_id');
|
||||||
let failure = document.getElementById('failure');
|
let failure = document.getElementById('failure');
|
||||||
|
let current_app = document.getElementById('current_app');
|
||||||
let current_room = document.getElementById('current_room');
|
let current_room = document.getElementById('current_room');
|
||||||
let set_room_id = document.getElementById('set_room_id');
|
let set_room_id = document.getElementById('set_room_id');
|
||||||
let set_user_color = document.getElementById('set_user_color');
|
let set_user_color = document.getElementById('set_user_color');
|
||||||
|
|
@ -221,9 +246,10 @@
|
||||||
|
|
||||||
// check cookie
|
// check cookie
|
||||||
let hw_id = getCookie('hw_id');
|
let hw_id = getCookie('hw_id');
|
||||||
|
|
||||||
if (hw_id !== "" && hw_id !== undefined && hw_id !== "undefined") {
|
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);
|
console.log(resp);
|
||||||
let respData = JSON.parse(resp);
|
let respData = JSON.parse(resp);
|
||||||
|
|
||||||
|
|
@ -231,20 +257,17 @@
|
||||||
window.location.href = "/pair";
|
window.location.href = "/pair";
|
||||||
}
|
}
|
||||||
|
|
||||||
writeClass('hw_id', respData['user']['hw_id']);
|
writeClass('hw_id', respData['device']['hw_id']);
|
||||||
writeClass('pairing_code', respData['user']['pairing_code']);
|
writeClass('pairing_code', respData['device']['pairing_code']);
|
||||||
writeValue('current_room', respData['user']['current_room']);
|
writeValue('current_app', respData['device']['current_app']);
|
||||||
writeClass('date_created', respData['user']['date_created'] + "<br>" + timeSinceString(respData['user']['date_created']) + " ago");
|
writeValue('current_room', respData['device']['current_room']);
|
||||||
writeClass('last_used', respData['user']['last_used'] + "<br>" + timeSinceString(respData['user']['last_used']) + " ago");
|
writeClass('date_created', respData['device']['date_created'] + "<br>" + timeSinceString(respData['device']['date_created']) + " ago");
|
||||||
writeValue('user_color', respData['user']['user_color']);
|
writeClass('last_modified', respData['device']['last_modified'] + "<br>" + timeSinceString(respData['device']['last_modified']) + " ago");
|
||||||
if (user_color) user_color.parentElement.style.color = "" + respData['user']['user_color'];
|
writeValue('user_name', respData['device']['friendly_name']);
|
||||||
writeValue('user_name', respData['user']['user_name']);
|
writeValue('avatar_url', respData['device']['data']?.['avatar_url']);
|
||||||
writeValue('avatar_url', respData['user']['avatar_url']);
|
writeValue('tv_url', respData['room']?.['data']?.['tv_url']);
|
||||||
if (respData['room']) {
|
writeValue('carpet_color', respData['room']?.['data']?.['carpet_color']);
|
||||||
writeValue('tv_url', respData['room']['tv_url']);
|
if (carpet_color) carpet_color.parentElement.style.color = "" + respData['room']?.['data']?.['carpet_color'];
|
||||||
writeValue('carpet_color', respData['room']['carpet_color']);
|
|
||||||
if (carpet_color) carpet_color.parentElement.style.color = "" + respData['room']['carpet_color'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Coloris({
|
Coloris({
|
||||||
|
|
@ -271,45 +294,61 @@
|
||||||
failure.style.display = "block";
|
failure.style.display = "block";
|
||||||
});
|
});
|
||||||
|
|
||||||
function setUserData(data) {
|
|
||||||
data["sender_id"] = "web";
|
function setDeviceField(data) {
|
||||||
httpPostAsync('/api/set_headset_details/' + hw_id,
|
fetch('/api/v2/device/set_data/' + hw_id, {
|
||||||
data,
|
method: 'POST',
|
||||||
(resp) => {
|
headers: {
|
||||||
console.log('success');
|
'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) {
|
function setRoomData(data) {
|
||||||
data["sender_id"] = "web";
|
fetch('/api/v2/set_data/' + current_app.value + "_" + current_room.value, {
|
||||||
httpPostAsync('/api/set_room_details/' + current_room.value,
|
method: 'POST',
|
||||||
data,
|
headers: {
|
||||||
(resp) => {
|
'Accept': 'application/json',
|
||||||
console.log('success');
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
(status) => {
|
body: JSON.stringify(data)
|
||||||
console.log('fail');
|
})
|
||||||
}
|
.then(_ => console.log('success'))
|
||||||
);
|
.catch(_ => console.log('fail'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set_room_id) {
|
if (set_room_id) {
|
||||||
set_room_id.addEventListener('click', () => {
|
set_room_id.addEventListener('click', () => {
|
||||||
setUserData({"current_room": current_room.value});
|
setDeviceField({"current_room": current_room.value});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (set_user_color) {
|
if (set_user_color) {
|
||||||
set_user_color.addEventListener('click', () => {
|
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) {
|
if (set_user_name) {
|
||||||
set_user_name.addEventListener('click', () => {
|
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) {
|
if (set_tv_url) {
|
||||||
|
|
@ -324,7 +363,7 @@
|
||||||
}
|
}
|
||||||
if (set_avatar_url) {
|
if (set_avatar_url) {
|
||||||
set_avatar_url.addEventListener('click', () => {
|
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>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -45,48 +45,48 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- <div class="hero bg-gray">
|
<!-- <div class="hero bg-gray">
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<h1>Pair your headset.</h1>
|
<h1>Pair your headset.</h1>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-image">
|
<div class="card-image">
|
||||||
<img src="/static/img/pair_code_screenshot.png" class="img-responsive">
|
<img src="/static/img/pair_code_screenshot.png" class="img-responsive">
|
||||||
</div>
|
</div>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-title h5">Enter Pairing Code</div>
|
<div class="card-title h5">Enter Pairing Code</div>
|
||||||
<div class="card-subtitle text-gray"></div>
|
<div class="card-subtitle text-gray"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
You can find the code in the bottom left of your menu tablet in conVRged.
|
You can find the code in the bottom left of your menu tablet in conVRged.
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer centered">
|
<div class="card-footer centered">
|
||||||
<input class="btn" type="text" id="pair_code" placeholder="0000">
|
<input class="btn" type="text" id="pair_code" placeholder="0000">
|
||||||
<button class="btn btn-primary" id="submit_pairing_code">Submit</button>
|
<button class="btn btn-primary" id="submit_pairing_code">Submit</button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
let submit_button = document.getElementById('submit_pairing_code');
|
let submit_button = document.getElementById('submit_pairing_code');
|
||||||
let pair_code_input = document.getElementById('pair_code');
|
let pair_code_input = document.getElementById('pair_code');
|
||||||
submit_button.addEventListener('click', () => {
|
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);
|
console.log(resp);
|
||||||
let respData = JSON.parse(resp);
|
let respData = JSON.parse(resp);
|
||||||
if (respData['hw_id'] != '') {
|
if (respData['hw_id'] !== '') {
|
||||||
setCookie('hw_id', respData['hw_id'], 60);
|
setCookie('hw_id', respData['hw_id'], 60);
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
}
|
}
|
||||||
}, (status) => {
|
}, (status) => {
|
||||||
window.location.href = "/failure";
|
window.location.href = "/failure";
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Loading…
Reference in New Issue