/// <summary> /// Call this method to initiate a calibration process of the /// selected PLTService. For example, if you call it for /// the MOTION_TRACKING_SVC it will cause a calibration /// (set to zero) of the motion tracking angles. /// </summary> /// <param name="aService">The PLTService type you want to calibrate.</param> public void calibrateService(PLTService aService) { switch (aService) { case PLTService.MOTION_TRACKING_SVC: m_quatproc.Calibrate(true); break; } }
/// <summary> /// Call this method to query if the specified service is currently subscribed /// </summary> /// <param name="aService">The PLTService enum value defines which service to check</param> /// <returns>Returns a boolean to indicate if service was subscribed or not.</returns> public bool getSubscribed(PLTService aService) { if (m_activeConnection != null) { return(m_activeConnection.isSubscribed(aService)); } else { throw new Exception("PLT Labs API getSubscribed: Sorry, you must connect to headset first (see openConnection method)"); } }
/// <summary> /// Call this method to unsunscribe a previously subscribed device service. /// </summary> /// <param name="aService">The PLTService enum value defines which service to unsubscribe from</param> public void unsubscribe(PLTService aService) { if (m_activeConnection != null) { m_activeConnection.unsubscribe(aService); } else { throw new Exception("PLT Labs API unsubscribe Service: Sorry, you must connect to headset first (see openConnection method)"); } }
/// <summary> /// Call this method to subscribe to the specified data service (PLTService enum) from the /// device. For example you can subscribe to motion tracking service to receive /// head tracking angles etc. /// </summary> /// <param name="aService">The PLTService enum value defines which service to subscribe to</param> /// <param name="aMode">The PLTMode defines On_Change (as soon as new data is available) /// or Periodic mode (return data on specific period). Note not all services are compatible /// with Periodic mode (These are not: Tap service, Free fall service and Call state service)</param> /// <param name="aPeriodmilliseconds">The period in milliseconds to return data /// if using Periodic mode</param> public void subscribe(PLTService aService, PLTMode aMode, int aPeriodmilliseconds = 0) { if (m_activeConnection != null) { m_activeConnection.subscribe(aService, aMode, aPeriodmilliseconds); } else { throw new Exception("PLT Labs API subscribe Service: Sorry, you must connect to headset first (see openConnection method)"); } }
internal PLTService[] getSubscribed() { PLTService[] retval = new PLTService[0]; lock (m_subscribedServicesLock) { retval = new PLTService[m_subscribedServices.Count()]; int i = 0; foreach (PLTServiceSubscription subscr in m_subscribedServices) { retval[i] = subscr.m_service; i++; } } return(retval); }
internal PLTServiceSubscription getSubscription(PLTService pLTService) { PLTServiceSubscription retval = null; lock (m_subscribedServicesLock) { foreach (PLTServiceSubscription subscr in m_subscribedServices) { if (subscr.m_service == pLTService) { retval = subscr; break; } } } return(retval); }
internal bool isSubscribed(PLTService pLTService) { bool retval = false; lock (m_subscribedServicesLock) { foreach (PLTServiceSubscription subscr in m_subscribedServices) { if (subscr.m_service == pLTService) { retval = true; break; } } } return(retval); }
/// <summary> /// Call this method to apply service-specific configurations to a service. /// For example, to configure the motion tracking service to provide only raw /// quaternions or calibrated quaternions (calibrated to a reference quaternion). /// Or to tell motion tracking service to provide quaternions as output or /// to also include orientations (Euler angles). /// </summary> /// <param name="aService">PLTService name being configured</param> /// <param name="aConfiguration">PLTConfiguration enum value of config to be applied</param> /// <param name="data">Optional reference to object for user data, e.g. a PLTQuaternion /// object as a user-supplied reference quaternion for calibration.</param> public void configureService(PLTService aService, PLTConfiguration aConfiguration, object data = null) { switch (aService) { case PLTService.MOTION_TRACKING_SVC: switch (aConfiguration) { case PLTConfiguration.MotionSvc_Offset_Raw: QuaternionProcessor.m_doCalibrate = false; break; case PLTConfiguration.MotionSvc_Offset_Calibrated: QuaternionProcessor.m_doCalibrate = true; // pass in optional data quat! double[] userquatvalues = null;; if (data != null) { try { PLTQuaternion userquat = (PLTQuaternion)data; userquatvalues = userquat.m_quaternion; } catch (Exception e) { throw new Exception("PLT Labs API Configure Service: Sorry, problem casting user calibration quaternion", e); } } m_quatproc.Calibrate(false, userquatvalues); break; case PLTConfiguration.MotionSvc_Format_Quaternion: QuaternionProcessor.m_doOrientation = false; break; case PLTConfiguration.MotionSvc_Format_Orientation: QuaternionProcessor.m_doOrientation = true; break; } break; } }
internal void unsubscribe(PLTService aService) { List <PLTServiceSubscription> m_deleteList = new List <PLTServiceSubscription>(); lock (m_subscribedServicesLock) { foreach (PLTServiceSubscription subscr in m_subscribedServices) { if (subscr.m_service == aService) { m_deleteList.Add(subscr); } } // now actually delete those found matching service type foreach (PLTServiceSubscription subscr in m_deleteList) { m_subscribedServices.Remove(subscr); } } }
public PLTServiceSubscription(PLTConnection aConnection, PLTService aService, PLTMode aMode, int aPeriodMilliseconds, object aLastdata = null) { m_pltconnection = aConnection; m_service = aService; m_mode = aMode; m_periodMilliseconds = aPeriodMilliseconds; m_lastData = aLastdata; // last data or initial value if (aMode == PLTMode.Periodic) { if (aPeriodMilliseconds < 1) { throw new Exception("Sorry, for periodic service subscription you must specify the period in milliseconds!"); } else { m_periodTimer = new Timer(); m_periodTimer.Interval = aPeriodMilliseconds; m_periodTimer.Elapsed += new ElapsedEventHandler(m_periodTimer_Elapsed); m_periodTimer.Start(); } } }
internal void subscribe(PLTService aService, PLTMode aMode, int aPeriodmilliseconds = 0) { // cannot subscribe to same service twice if (isSubscribed(aService)) { return; } bool doSubscribe = false; object lastData = null; // work out if we can/should subscribe to the service switch (aService) { case PLTService.MOTION_TRACKING_SVC: // TODO add to Spokes knowledge of which device // has motion tracking. For now just assume all // devices do. doSubscribe = true; break; case PLTService.MOTION_STATE_SVC: // TODO: does the headset provide this info? throw new Exception("Sorry, motion state service is not yet implemented."); doSubscribe = false; break; case PLTService.SENSOR_CAL_STATE_SVC: doSubscribe = true; break; case PLTService.PEDOMETER_SVC: doSubscribe = true; break; case PLTService.TAP_SVC: if (aMode == PLTMode.On_Change) { doSubscribe = true; } else { throw new Exception("Sorry, tap service only supports PLTMode.On_Change mode (not PLTMode.Periodic)."); } break; case PLTService.WEARING_STATE_SVC: if (m_spokes.DeviceCapabilities.HasWearingSensor) { doSubscribe = true; lock (m_pltlabsapi.m_lastwornstateLock) { lastData = m_pltlabsapi.m_lastwornstate; } } else { throw new Exception("Sorry, device does not have a wearing sensor. Unable to subscribe to wearing sensor data."); } break; case PLTService.FREE_FALL_SVC: if (aMode == PLTMode.On_Change) { doSubscribe = true; } else { throw new Exception("Sorry, tap service only supports PLTMode.On_Change mode (not PLTMode.Periodic)."); } break; case PLTService.PROXIMITY_SVC: // Don't bother checking m_spokes.DeviceCapabilities.HasProximity, as this is // generally populated with correct value later asyncronously if enable proximity call // succeeded doSubscribe = true; lock (m_pltlabsapi.m_lastproximitystateLock) { lastData = m_pltlabsapi.m_lastproximitystate; } break; case PLTService.CALLERID_SVC: doSubscribe = true; lock (m_pltlabsapi.m_lastcalleridLock) { lastData = m_pltlabsapi.m_lastcallerid; } break; case PLTService.CALLSTATE_SVC: if (aMode == PLTMode.On_Change) { doSubscribe = true; lock (m_pltlabsapi.m_lastcallstateLock) { lastData = m_pltlabsapi.m_lastcallstate; } } else { throw new Exception("Sorry, call state only supports PLTMode.On_Change mode (not PLTMode.Periodic)."); } break; case PLTService.DOCKSTATE_SVC: doSubscribe = true; lock (m_pltlabsapi.m_lastdockstateLock) { lastData = m_pltlabsapi.m_lastdockstate; } break; case PLTService.CHARGESTATE_SVC: // todo consider not making wireless devices subcribe - no battery doSubscribe = true; lock (m_pltlabsapi.m_lastbattstateLock) { lastData = m_pltlabsapi.m_lastbattstate; } break; //case PLTService.TEMPERATURE_SVC: // doSubscribe = true; // break; } if (doSubscribe) { PLTServiceSubscription subscr; subscr = new PLTServiceSubscription(this, aService, aMode, aPeriodmilliseconds, lastData); lock (m_subscribedServicesLock) { m_subscribedServices.Add(subscr); } // NOTE: for SOME services we want to ship the last known value right // away to connected app, because for those services such as wearing sensor // the last known value will be the "initial" value. (Does not apply to // headtracking). if (aService == PLTService.WEARING_STATE_SVC || aService == PLTService.CHARGESTATE_SVC ) { ShipLastKnownDataToAppForService(aService, subscr); } } }
// a periodic service subscription timer has fired // ship the last known data to the connected app internal void ServiceTimerElapsed(PLTService aService, PLTServiceSubscription aSubscription, object lastSubscriptionData) { ShipLastKnownDataToAppForService(aService, aSubscription); }
// Pass lastSubscriptionData to contain reference to last value for this subscription // or NULL where no value is available (for instance with wearing sensor before // a subcription has been made). private void ShipLastKnownDataToAppForService(PLTService aService, PLTServiceSubscription aSubscription) { if (m_pltlabsapi. m_callbackhandler != null && m_pltlabsapi.m_activeConnection != null && aSubscription != null) { // now work out if we should send the last known value (applies to some services // e.g. wearing sensor, so app can receive initial value) switch (aService) { case PLTService.MOTION_TRACKING_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTMotionTrackingData)aSubscription.LastData)); break; case PLTService.MOTION_STATE_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTMoving)aSubscription.LastData)); break; case PLTService.SENSOR_CAL_STATE_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTSensorCal)aSubscription.LastData)); break; case PLTService.PEDOMETER_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTPedometerCount)aSubscription.LastData)); break; case PLTService.TAP_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTTapInfo)aSubscription.LastData)); break; case PLTService.WEARING_STATE_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTWearingState)aSubscription.LastData)); break; case PLTService.FREE_FALL_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTFreeFall)aSubscription.LastData)); break; case PLTService.PROXIMITY_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTProximityType)aSubscription.LastData)); break; case PLTService.CALLERID_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTCallerId)aSubscription.LastData)); break; case PLTService.CALLSTATE_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTCallStateInfo)aSubscription.LastData)); break; case PLTService.DOCKSTATE_SVC: m_pltlabsapi. m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTDock)aSubscription.LastData)); break; case PLTService.CHARGESTATE_SVC: m_pltlabsapi.m_callbackhandler.infoUpdated( m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTBatteryState)aSubscription.LastData)); break; //case PLTService.TEMPERATURE_SVC: // m_pltlabsapi. // m_callbackhandler.infoUpdated( // m_pltlabsapi.m_activeConnection, new PLTInfo(aService, (PLTTemperature)aSubscription.LastData)); // break; } } }
/// <summary> /// Internal method to send either a subscribe or unsubscribe BladeRunner command /// to the BladeRunner device that represents this PLTConnection. /// </summary> /// <param name="subscribe"></param> /// <param name="aService"></param> /// <param name="aMode"></param> /// <param name="aPeriodmilliseconds"></param> private void SendBladeRunnerSubscribeCommand(bool subscribe, PLTService aService, PLTMode aMode = PLTMode.On_Change , int aPeriodmilliseconds = 50) { if (!subscribe) { aMode = PLTMode.Off; // unsubscribe! } switch (aService) { case PLTService.MOTION_TRACKING_SVC: // Head orientation 0x0000<br/> // Pedometer 0x0002<br/> // Free Fall 0x0003<br/> // Taps 0x0004<br/> // Magnetometer Calibration Status 0x0005<br/> // Gyroscope Calibration Status 0x0006<br/> // Versions 0x0007<br/> // Humidity 0x0008<br/> // Light 0x0009<br/> // Optical proximity 0x0010<br/> // Ambient Temp 1 0x0011<br/> // Ambient Temp 2 0x0012<br/> // Skin Temp 0x0013<br/> // Skin Conductivity 0x0014<br/> // Ambient Pressure 0x0015<br/> // Heart Rate 0x0016<br/> //The update mode for the service.<br/> // 0 = off,<br/> // 1 = on-change,<br/> // 2 = periodic<br/> if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceSensorService(m_device.m_device, 0, (int)aMode, aPeriodmilliseconds); } break; case PLTService.PEDOMETER_SVC: if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceSensorService(m_device.m_device, 2, (int)aMode, aPeriodmilliseconds); } break; case PLTService.FREE_FALL_SVC: if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceSensorService(m_device.m_device, 3, (int)aMode, aPeriodmilliseconds); } break; case PLTService.TAP_SVC: if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceSensorService(m_device.m_device, 4, (int)aMode, aPeriodmilliseconds); } break; case PLTService.SENSOR_CAL_STATE_SVC: if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceSensorService(m_device.m_device, 5, (int)aMode, aPeriodmilliseconds); } if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceSensorService(m_device.m_device, 6, (int)aMode, aPeriodmilliseconds); } break; case PLTService.WEARING_STATE_SVC: if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceWearingStateService(m_pltlabsapi.m_wearingsensorDevice.m_device, true); } break; case PLTService.PROXIMITY_SVC: if (m_pltlabsapi != null) { m_pltlabsapi.RegisterForDeviceProximityService(m_pltlabsapi.m_proximityDevice.m_device, true); } break; } }
/// <summary> /// The PLT default constructor /// </summary> /// <param name="serviceType">PLTService enum value</param> /// <param name="data">object pointer to returned data</param> public PLTInfo(PLTService serviceType, object data) { m_serviceType = serviceType; m_data = data; }