Setting trainer resistance using Swifty Sensors and Wahoo's cycling power service extension - swift

I'm using the SwiftySensors CocoaPod to connect to a Wahoo Smart Trainer. It's advertising CyclingPowerService and DeviceInformationService. I've been able to get speed and power values without issue. Wahoo apparently extended the CyclingPowerService standard to allow setting resistance via that service instead of the Fitness Machine Control service.
https://github.com/codeinversion/sensors-swift links out to another Github page dealing with that extension, but that link is broken.
My question is: how should I go about setting the trainer's resistance? Wahoo's app can do it, so the machine is equipped for it. This is the only time I need to change the trainer's settings. Otherwise, I'm just reading sent information and SwiftySensors works great.
I've referenced the following post: Writing BLE to Cycling Control Point - Adding Resistance. Someone there said using CyclingPowerService to set resistance was possible without offering any guidance. I'm not very experienced with Bluetooth, so any information would be great!

Thank you Jordan. That was the answer. The broken link I referenced must have been pointing to the following repo: https://github.com/WahooFitness/sensors-swift-trainers
The following instructions assume that you're already able to connect to the trainer to receive data from it, like speed and power, using the SwiftySensors CocoaPod and the CyclingPowerService. Using the repo linked above, I was able to set the resistance to the Wahoo Snap trainer. Note that after you install that new repo, before you start scanning for sensors to connect to, you need to call
CyclingPowerService.WahooTrainer.activate()
From there, you set the resistance with
if let wahooTrainer = cyclingSpeedService.wahooTrainer {
wahooTrainer.setResistanceMode(resistance: 0.5)
}
The resistance is set using percentages. The value for resistance will be a Float, somewhere between 0 and 1.

Related

How to send custom dimensions, medium, source or referer with an event via Measurement Protocol V2?

With v1 of the measurement protocol, you could use these parameters to add custom dimensions or change medium, source or refer for a page view:
https://ssl.google-analytics.com/collect?v=1&tid=UA-xxxxxxxx&cid=[custom-id]&t=pageview&dp=[Url of pageview]&dh=[hostname of pageview]&cm=[new-medium]&cs=[new-source]&dr=[new-referer]&cd1=[custom-dimension-1]&cd2=[custom-dimension-2]
How is it done in measurement protocol v2?
I couldn't find any documentation about the page-view-event in V2 (for example it's just not mentioned here
https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events), even the event-builder (https://ga-dev-tools.web.app/ga4/event-builder/) doesn't support a simple page-view.
So, all I got so far is this:
$data = '
{ "client_id": "'.[custom-id].'",
"events": [
{
"name": "page_view",
"params": {
"page_location": "'.[Url of pageview].'"
}
}
]
}
';
So, what are possible parameters for a page-view-event?
Ok, a few things here right away that you should know if you're playing with MP:
Measurement protocol is a poor name. It implies there's more than one protocol for data gathering. There's none. There is just only one protocol for tracking.
MP2 still largely MP1. Google tries to pose GA4 as a new product, but it's just our old good GA UA with a simplified backend and overengineered front-end that tries to deliver the level of quality Site Catalyst/Omniture/Adobe Analytics have been delivering for a decade. MP is largely the same. dr, cm, cs and a lot of other fields are still there. cds aren't there anymore cuz they're replaced with eps and ups, but more about that a bit later.
GA4 uses this big marketing claim that the new analytics is so wonderfully event-based, unlike the old one. When I dug into why they keep claiming it everywhere, I realized that the only difference is that pageviews are now events. Not much difference really. But yes, a pageview is just an event named page_view. We'll talk about it a bit more later.
Custom dimensions are no more. Now they're called event properties and user properties. The same thing really, Google just tries to make it less obvious that there are no more session level custom dimensions. Or product-level CDs. Though the product level is seemingly on their roadmap.
Make sure you're using the correct measurement id. They made it a lot harder to find it in GA4. It's no longer just the property id visible in the property list, unfortunately.
GA's real-time reports don't include all dimensions, especially if those dimensions are involved in advanced metrics/dimensions calculations. Do not use real time reports for inspecting the content of your events. It's not meant for debugging. It's a vanity report. Still helpful to check the volume of events when you're sending a bunch and expect to see them in GA. Google even has a warning here:
Like the DebugView report, the Realtime report performs limited attribution analysis to ensure responsive reporting. We recommend that you refer to the Acquisition reports for the most accurate attribution information.
Finally, what I often do instead of reading the so-still-unfinished-and-not-really-helpful documentation on MP2, is either use a library like this.
Or, since 1 is the case, I would just implement a moniker tracking in my test GTM, then see what and how it sends to where in the Network debugger and simply reimplement it on my side exactly how GTM does it. No magic involved. Here is how my GTM tag would look like:
With a trigger on any click or any page load. After all is done, I publish the lib. Then I would inject this GTM's code in a local site, or in my test site, or however else you want to test it. And trigger the tag that you need to mimic with MP.
I use this wonderful extension to show all events that fire and their details right in my console.
Now this is how the above tag looks on my test site through the extension:
It's pretty useful.
How do I know that page_referrer is used as dr instead of ep in GTM? Here is the list of the fields that will never be seen as ep. But Google doesn't care enough to map them properly to what these fields are called in MP, so you either have to test, or know, or google it elsewhere.
Finally, here is how the network request looks like:
I published the tag to prod (I keep a test site in prod), so you can go and look at it. Or just find a site that uses GA4 and see its network requests. How does google know that this is a pageview? by the event name: en=page_view
Of course, you do the same with medium and source. Judging from the documentation I've linked to above, the medium and source look like campaign_source and campaign_medium in GTM. GTM maps them accordingly to cs and cm fields. And that's how you know these are the correct mp fields. Give GA time to process these and check on them in a few days.
Good, now this is applicable to the enhanced ecommerce hits too, it's just that they have more variables and data structures in them typically.
Finally, if you want to simulate batch events, you can just make a few tags fire in rapid succession and GTM will neatly pack them in one network request if they fit. You can then digest how the packing is done through the same methods as we do here and simulate.

Connecting a device to an account

So the title sounds stupid. I'm not really sure how to really word it, but I want someone to help guide me on what to look for. Little back story first so I'm working on a Raspberry Pi project that involves using an LTE service currently I have a dashboard running on a AWS EC2 web server with a simple user working user login.
I have a raspberry pi that is directly pointed to the dashboard/account via an IP address. I want to know how to do something like giving a device an ID and having it connect to an account. So for example with Nest products you have the QR code on the camera you take a photo and that devices get applied to your account.
Is this even possible with Raspberry Pi(I'm sure anything possible, but is it feasible? If so what should I look into or learn how to do such thing. I know its not something that can be answered in a short paragraph just looking for some guidance.
Right, thanks. Well, I think you need to program this into the pi server app. So currently your Pi is reading a sensor and sending this data to the web server, right? I suppose you have a daemon running, taking readings, and doing an API REST call to the server backend, correct? So what you want is to have a unique code for each pi, sent with the API call, and then on your DB server side,you store all readings related to their unique code.
You don't need to pre-validate this code, there are GUID generators that will create a number for you, guaranteed to be unique for all eternity, so on the PI, you set it up once, to create the PI's code, and use it from then on. Now, server side, then associating a device with a user is a matter of choosing the data associated with a given gui. And I think that covers it.
You can improve on this basic idea by giving it more thought, but I think it's a good starting point! Do let me know if I can help you with anything else!

AIR server connections

I am wanting to give back to a small gaming community. The idea is to make an app that acts like a chat client to connect to the game servers. I am trying to grasp the concepts on how connections work through examples I've found on the web, since I am self taught by seeing examples.
So far the examples I found are for connections on the same network. What I need is some kind of example that will allow me to connect from different networks or at least an explanation on what I need to do. Also I need to be able to get around a router without with setting port forwarding on the router.
In the end the app will be connecting to the game developer's server but I need a working app before I get his permission to connect to his servers.
Any help will be most appreciated. If any additional information is needed to help just ask and I'll do my best to fill in the gaps.
That is a very broad question, but I try to give you as much information as possible from by point of view. As I'm not yet sure if you want to have a P2P Connection (game-application to game-application) or a standard server model, I will just mentioned different approaches to this problem.
Adobe has support for P2P since a long time. Read some FAQ, esspecially "How does RTMFP differ from RTMP?" (I try to choose Sources with infographics, as that helped me to understand it).
What you really should start playing with and making first steps in, should be NetConnection. This is the very basic Function that will allow you to communicate to a Server running e.g. PHP or connecting to a Flash Media Server (FMS). FMS is inpartcular interresting for you, as it really boosts the ideas what you game could do, but setting up a FMS is not that easy,to host a own instance is even more complex. So if you come to the conclusion that you want to travel the road of using a FMS, I can suggest you Onyx Server. They mainly marketing theirself as a Streaming service, but in reality you will get access to a FMS for a ok'ish price (FMS instances on Amazon were way worst the last time I checked).
The FMS basicly only a Flash AS2 File with some extra Commands. Your FMS can handle real-time (!) persistent connections (!) with any client that connects to it. Everyone is able to connect to the server at first, and you can then choose in your FMS Script what a client have to bring to the table to stay on the server or is rejected. After that, you have a very string tool for a Game. For example, you could have a game instance connect to it, tell the server that an enemy was hit and the server near-instantly (the speed is really amazing, there is no feeled delay, it really is instant. Its called SharedObjects) pass this information down to the enemy game instance. I used FMS only for one project and it was a very long ride to understand it and work with it, but it was a really nice experience, as you code the Server in the "same" language like the game itself (AS2, AS3 = ECMA).
If you dont want to spend money at this stage, you can use the Adobe RTMFP Instance at p2p.rtmfp.net. It is, as far as I know, only for testing and you will be rejected if you misuse the service for a real project, but for starting and testing it will do. If you use the Cirrus Engine, you can even follow this Tutorial. You will find sample code in there:
// Cirrus connect info
private const SERVER:String = "rtmfp://p2p.rtmfp.net/";
private const DEVKEY:String = "{YOUR_DEVELOPER_KEY}";
// Used to connect to the Cirrus service
private var _netConnection:NetConnection;
_netConnection = new NetConnection();
// Listen for status info
_netConnection.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
// Connect to Cirrus using our unique URI
_netConnection.connect( SERVER + DEVKEY );
My adive for you would be: Try getting comfortable with NetConnection. It is really straight forward. When I first started using it, I had a couple of days struggeling and reading a lot on the web, but I learned a lot doing so. You should too. Use NetConnection and try to create two simple AS3/FLA instances of your code that both connect to the same domain (use the adobe rtmfp domain for now) and try to exchange some simple String-Data between these instances.
To take some of the pain of your shoulders, add the minimum amount of listeners to your NetConnection like so:
//Main NetConnector
nc = new NetConnection();
//Troubleshooting Listener
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
nc.addEventListener(NetStatusEvent.NET_STATUS, status_handler);
//nc.objectEncoding = ObjectEncoding.AMF0; //Default
nc.client = this;
nc.connect("https://some-domain");
////////////////////////////////////////////////////////////////////////////////
/// CALL ERROR LISTENER
////////////////////////////////////////////////////////////////////////////////
private function status_handler(e:NetStatusEvent):void {
//trace("NetStatusEvent");
dispatchEvent(new CallEvent(CallEvent.CALL_NATIVE_NET_STATUS, e, true ));
}
private function securityErrorHandler(e:SecurityErrorEvent):void {
//trace("SecurityErrorEvent");
dispatchEvent(new CallEvent(CallEvent.CALL_NATIVE_SECURITY_ERROR, e, true ));
}
You will get alot of errors and netStatus and NetSecuriy Events. Flash will often run into Sandbox-Violation errors when you now know what you are doing. That can be frustrating but if you keep it up, google every error and compare you implementations with the implementation of others, you will wrap your head around this and can do really neat stuff with it.
I recommend you google sources and tutorials for NetConnection and stick to one that is on your level of knowledge.
Good Luck.

Directly connecting two Arduino Yun boards to each other

I am trying to connect two Arduino Yun boards to each other via WIFI (make one board control a pin on the other board an vice versa) and I am having trouble making it work the way I want to.
This is where I've gotten so far:
I have two Arduino Yun boards with a simple sketch installed on each, which works fine as long as I keep the "connecting-each-other"-part out of it. It uses a potentiometer on the analog port, reads its value, maps it to the range of 0-255 an fades a LED up or down on one of the digital pins (brighter / darker) depending on the given value. Now I want to use the potentionmeter of one board to control the LED on the OTHER board.
To do that, I tried to use the REST API. I combined my sketch with the code from the "Bridge" Example Sketch, which sets up a http-client/server on the Arduino Yun (on the Linux part) allowing it to receive requests to control and read patricular pins via http.
When using the specific URL for the REST API in a browser, it works fine. For example: when I type "http://myarduino.local/arduino/digital/3/1" it sets the value of digital pin 3 to 1 (i.e. LED is switched on) --> so that's all fine
I am not sure how to continue at this point, since I dont want to control the board from a browser or app but make one Arduino Yun control another Arduino Yun directly. If I put a http request in my sketch like mentioned above via client.get and client.read (as in the example sketch) it does not work. See example code below. It doesnt have any effect nor does anything appear in the serial monitor (with the original URL "http://arduino.cc/asciilogo.txt" like in the example, the ascii code appears in the serial monitor)
HttpClient webclient;
webclient.get("http://ardu1.local/digital/3/1");
while (webclient.available()) {
char c = webclient.read();
Serial.print(c);
}
Serial.flush();
I am a beginner with Arduino Yun boards and maybe I am missing something?
Thanks for any help or pointing me in the right direction. Or if you need more information to help me with this problem, please let me know.
I found another way to connect two Arduino Yun boards directly, or as close to "directly" as it probably gets. The REST API was not the right way to go. So this is for anyone who might encounter the same "problem":
After some research I came across "Spacebrew". It's based on "websockets" and requires a server to connect the boards to each other, but it is very flexible. It's also fairly easy to setup a spacebrew server locally. It allows every client (like a Arduino Yun board) connected to the server to publish different types of data (boolean, range, value) and/or to subscribe to the published data from other devices using a simple webinterface. The good thing is, that the connection is fast and there's no waiting for the connection to be reestablished when there is data to be sent.
I used the Arduino Example Sketch "spacebrewRange" and it worked fine for me.
It also requires a few other things before it can work, but its explained on the website and in a tutorial:
http://docs.spacebrew.cc/gettingstarted/
http://de.slideshare.net/julioterra/spacebrew-server-workshop-itp
Trying to do the same, it seems, and for me it works (this bit at least :-|
I let one arduino request the URL "http://router.domain:port/arduino/key/value", using a Process which runs cURL. The receiving arduino interprets this request to set the key to the value, using a YunClient.
From the URLs in your question, it seems that you are missing the mandatory "/arduino/" component in the path name. As far as I know, this is needed to direct any requests directed at the OpenWRT stack to the arduino/Leonardo part.

Is there any way to get the tamper-proof date and time on iPhone?

For various reasons I need to get from the iPhone the current date and time that can't be meddled with by the user. Yes, I've seen how one can check a server (e.g., here), but that's not invulnerable to tampering if you take a moment to reflect.
There are two knee-jerk reactions I'm expecting to hear:
Use the GPS time.
It can't be done.
In answer to another question, I've described my researches into this matter. To summarize them:
The GPS time shifts with the user-defined settings.
The iPhone definitely has an internal tamper-proof time and date, as shown when date-time reverts after Set Automatically in Settings > General > Time & Date is turned back to on even in a fallout shelter.
What I want to know is how to access this tamper-proof time.
Edit
Just to be clear, the server-based solution is not suitable. For one, it could be faked. For another, the app needs to work without a network connection.
Assuming you always have Internet available, you could implement a class or object that connects to a remote Network Time Protocol server.
Here's an open source GitHub project that should get you started, and the related StackOverflow question I found it at.