How to receive cumulocity real time notifications with SmartREST? - complex-event-processing

We use the cumulocity REST API. Regular real time notifications work, e.g. we subscribe to /alarms/*, start our connection/polling loop and when we create an alarm we receive the expected JSON. We did not install any specific modules or statements, it just works.
But when we try to do the same with SmartREST we receive this error, as soon as the alarm is created:
40,,/alarms/177649296,Could not find any templates subscribed for the channel
Following the reference guide (http://cumulocity.com/guides/reference/smartrest/) we tried it like this, where all requests have the same X-Id-header and all requests result in the expected http status 200 and no error messages, except for the last one:
Register a smart response template by doing a POST to /s
Body: 11,102,,,$.channel
Handhake: POST to /cep/realtime
Body: 80
Response is our clientId (e.g. 191het1z38bp7iq1m96jqqt8jnef)
Subscribe: POST to /cep/realtime
Body: 81,191het1z38bp7iq1m96jqqt8jnef,/alarms/*
Connect: POST to /cep/realtime
Body: 83,191het1z38bp7iq1m96jqqt8jnef
In the normal REST case the notification consists of a JSON array with 2 elements, both of which have a property "channel". So that is what we would expect from our response template. Instead, we get the aforementioned error 40.
Is our response template wrong? Is it not properly matched by the X-Id? What does it mean, that there are no "templates subscribed for the channel"? The subscriptions are done for a clientId, and not for a specific response template, and the templates are supposed to be matched automatically anyway. So probably "template" means "X-Id" here? The documentation seems ambiguous as to the meaning of that word. But anyway, we did use the same X-Id header in all of the requests.
Any pointer about what we're doing wrong would be appreciated, since we tried pretty much anything by now.

The SmartREST protocol was developed for a IoT-device <-> platform communication. So there was never any design around using it to subscribing to realtime data (except of course for the operations a device needs) as usually devices to not need subscribe to the data that they created themselves.
That said it is possible to use it but with a couple of limitations. Your approach is basically correct but there is one problem with the subscription. The wildcard subscriptions will not work with SmartREST because on subscription it links your X-Id with the channel you subscribed to but there is never a message published on the channel /alarms/*. Thus this kind of weird error message that said that there was no template subscribed for the channel the alarm appeared on. Inside CometD you still receive the alarm because of the wildcard subscription but the SmartREST part does not work.
The messages are published on the channel with the deviceId (e.g. /alarms/12345).
If you subscribe to /alarms/12345 it will work. You can of course subscribe to as many channels as you want but wildcard subscription won't work.
Regarding the templates you need to know the following. The SmartREST parsing is not done on the raw JSON of CometD but on the payload inside it (e.g. the alarm). So a template for an alarm could look like this:
11,500,,$.severity,$.id,$.type,$.severity
This would trigger only if the object has a severity and would return id, type and severity.

Related

GA4 Conversion tracking using Measurement Protocol

[Edited. Added code sample and more explanations]
Is anybody familiar with the GA4 Measurement Protocol?
We are sending events from our backend servers to the server-side GTM container using the GA4 Measurement Protocol. Everything works fine except for conversion tracking. The events marked as conversion are not counted as conversions if we send those via MP (except for the default "purchase" event, it works perfectly). The same event with the same parameters counts as a conversion if we send it from the browser (client-side GTM). As I couldn't find anything about this issue online, the only thing left was to debug parameter by parameter using the server-side GTM preview mode. Here I discovered, that if I send events from the browser, the requests for events I mark as conversions in GA have "&_c=1" in their query string.
That means, as far as I understand it, that in order to get conversion events via MP, the event request needs to have "_c" query string parameter. I tried adding "_c" as an event param, but that didn't work. Is there a designated JSON parameter to mark the event as a conversion?
------------MORE INFO--------------
Here is an example of an event "Experts". This event gets sent from both the client-side and the server. As you can see in the screenshot, this event is marked as a conversion.
As you can see on the second screenshot, the actual events (137) are much more than the conversions detected (48). The difference are exactly the ones sent from the server-side.
Here is the request body of the server call:
{
"client_id":"Z9TLWnyVC2UK4UssPIVk8J+2n5BZhgWLtWSlFYYSwlg=.1642076344",
"user_id":"119412",
"events": [{
"name": "Experts",
"params": {
"tenweb_action": "[Test action]",
"tenweb_info": "[Some more info]",
"debug_mode":1,
"page_location": "https://10web.io/[some-test-page]"
}
}]
}
#Jan, #DaImTo, and everyone else that might have this issue in the future.
I think I've found a solution. Although it's unofficial and might break at any moment, it's the best one I've found so far. Here is what I ended up doing. While debugging via GTM preview mode I noticed, that in Event Data tab of conversion events there is an object "x-ga-system_properties", that, among other system variables, contains c:"1" . So I tried adding
"x-ga-system_properties":{"c":"1"}
to the event parameters JSON that we send to the Measurement Protocol endpoint of our server-side GTM.
IT WORKED. The events sent that way were registered as conversions by GA4.
Would be great to hear your thoughts on this. Do you think it's a stable solution? Do you think there will be official documentation on this from Google?

How to properly send event parameters with Facebook Server Events

I am setting Facebook Pixel for the first time with the Conversions API and all my TestEvents are correct and I am receiving the events I am supposed to. But in every event under "Overview" I have this error:
No event parameters were detected. Use Test events to view the parameters of an individual event trigger.
I am new to this so I don't even know if this is an error or if it should work like that.
I am having a similar problem.
I am sending Custom Events. The Pixel and Server events are successfully deduplicating. Custom parameters are within both tags, however while the custom parameters are successfully being sent (& are hence visible in Events Manager Test Events) by the Pixel tags, the custom parameters are missing when viewing the Server Events in Test Events.
I have used both Custom HTML tags originally, and now the Facebook tag template, but and have endlessly tweaked the settings, but just cannot resolve this.
Let me know if you made progress!
Here are some good links that may help you
https://www.simoahava.com/analytics/facebook-conversions-api-gtm-server-side-tagging/
https://www.simoahava.com/custom-templates/facebook-pixel/
https://www.optimizesmart.com/gtm-server-side-tagging-for-facebook/

Is it possible to have Lync communicate with a REST API?

I have created a basic REST API where a user can ask for an acronym, and the web-page will return the meaning of the acronym via a POST call.
The majority of my end-users don't use the Internet as much as they use the Microsoft Lync application.
Is it possible for me to create a Lync account, and have it pass questions to my API, and return the answers to the user? Meaning the user just needs to open a new chat in Lync rather than a new web-page.
I'm sure this is possible, but I can't find any information on Google or on the web. How can this be accomplished?
Thanks very much.
Edit :
Adding a bounty in the hopes of someone creating a simple example as I believe it would be very useful for a large number of devs :).
Yep, absolutely. UCMA (the Unified Communications Managed API) would be my choice of API to use here, and a good place to start - UCMA apps are "normal" .net applications, but also expose an application endpoint, which can be added to a user's contact list. When users send messages, that can trigger events in your application so you can take the incoming IM, do the acronym translation and return the full wording.
I have a bunch of blog posts about UCMA, but as of yet no defined collection of "useful" posts to work through, but coming soon! In the meantime, feel free to browse the list.
-tom
To elaborate on Tom Morgan's answer, it would be easy to create an UCMA application for this.
Create an UCMA application
Now this doesn't have to be complicated. Since all you want is to receive an InstantMessage and reply to it, you don't need the full power of a trusted application. My choice would be to use a simple UserEndpoint. As luck would have it, Tom has a good example of that online: Simplest example using UCMA UserEndpoint to send an IM.
Make it listen to incoming messages
Whereas the sample app sends a message when it is connected, we need to listen to messages. On the UserEndpoint, set a message handler for instant messages:
endpoint.RegisterForIncomingCall<InstantMessagingCall>(HandleInstantMessagingCall);
private void HandleInstantMessagingCall(object sender, CallReceivedEventArgs<InstantMessagingCall> e)
{
// We need the flow to be able to send/receive messages.
e.Call.InstantMessagingFlowConfigurationRequested += HandleInstantMessagingFlowConfigurationRequested;
// And the message should be accepted.
e.Call.BeginAccept(ar => {
e.Call.EndAccept(ar);
// Grab and handle the toast message here.
}, null);
}
Process the message
There is a little complication here, your first message can be in the 'toast' of the new message argument, or arrive later on the message stream (the flow).
Dealing with the Toast message
The toast message is part of the conversation setup, but it can be null or not a text message.
if (e.ToastMessage != null && e.ToastMessage.HasTextMessage)
{
var message = e.ToastMessage.Message;
// Here message is whatever initial text the
// other party send you.
// Send it to your Acronym webservice and
// respond on the message flow, see the flow
// handler below.
}
Dealing with the flow
Your message flow is where the actual data is passed around. Get a handle on the flow and store it, because it's needed later to send messages.
private void HandleHandleInstantMessagingFlowConfigurationRequested(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
{
// Grab your flow here, and store it somewhere.
var flow = e.Flow;
// Handle incoming messages
flow.MessageReceived += HandleMessageReceived;
}
And create a message handler to deal with incoming messages:
private void HandleMessageReceived(object sender, InstantMessageReceivedEventArgs e)
{
if (e.HasTextBody)
{
var message = e.TextBody;
// Send it to your Acronym webservice and respond
// on the message flow.
flow.BeginSendInstantMessage(
"Your response",
ar => { flow.EndSendInstantMessage(ar); },
null);
}
}
That would about sum it up for the most basic example of sending/receiving messages. Let me know if any parts of this need more clarification, I can add to the answer where needed.
I created a Gist with a full solution. Sadly it is not tested because I'm currently not near a Lync development environment. See UCMA UserEndpoint replying to IM Example.cs.
I never used Lync but while I was looking at the dev doc, I stumble upon a sample which could be what you're looking for.
Lync 2013: Filter room messages before they are posted
Once you have filtered the messages, you just need to catch the acronym and call your custom code that calls your API.
Unless I'm missing something, I think you could do it with a simple GET request as well. Just call your API like this yoursite.com/api/acronym/[the_acronym_here].
You can use UCWA (Microsoft Unified Communications Web API),is a REST API.For detail , can reference as the following..
https://ucwa.lync.com/documentation/what-is-lync-ucwa-api

Real time model events in Sails.js 0.10-rc5

I've been playing around with building some realtime functionality using Sails.js version 0.10-rc5 (currently the #beta release).
To accomplish anything, i've been following the sweet SailsCast tutorial on this subject (sailsCast link)
It talks about subscribing to a model via a 'subscribe' action within the model's controller. Then listening to it at the client side, waiting for the server to emit messages. Quite straightforward, although I do not seem to receive any messages.
I'm trying to do this to get real-time updates on anything that changes in my User models, or if new ones get created.. So I can display login status etc. in real time. Pretty much exactly the stuff that's explained in the sailsCast.
In my terminal i'll get two things worth noticing, of which the first is the following:
debug: Deprecated: `Model.subscribe(socket, null, ...)`
debug: See http://links.sailsjs.org/docs/config/pubsub
debug: (⌘ + double-click to open link from terminal)
debug: Please use instance rooms instead (or raw sails.sockets.*() methods.)
It seems like the 'subscribe' method has been deprecated. Could anybody tell me if that's correct, and tell me how to fix this? I've been checking out the reference to the documentation in the debug message, although it just points me to the global documentation page. I've been searching for an answer elsewhere, but haven't found anything useful.
The second message I'm getting is:
warn: You are trying to render a view (_session/new), but Sails doesn't support rendering views over Socket.io... yet!
You might consider serving your HTML view normally, then fetching data with sockets in your client-side JavaScript.
If you didn't intend to serve a view here, you might look into content-negotiation
to handle AJAX/socket requests explictly, instead of `res.redirect()`/`res.view()`.
Now, i'm quite sure this is because I have an 'isAuthenticated' policy added to all of my controllers and actions. When a user is not authenticated, it'll redirect to a session/new page. Somebody must log in to be able to use the application. When I remove the 'isAuthenticated' policy from the 'subscribed' action, the warnings disappear. Although that means anyone will get updates via sockets (when I get it to work), even when they're logged out. - I don't really feel like people just sitting at the login screen, fishing out the real time messages which are intended only for users who are logged in.
Can anyone help me getting the real time updates to work? I'd really appreciate!
As far as the socket messages not being received, the issue is that you're following a tutorial for v0.9.x, but you're using a beta version of Sails in which PubSub has gone through some changes. That's covered in this answer about the "create" events not being received.
Your second issue isn't about sockets at all; you'll just need to reconsider your architecture a bit. If you want to to use socket requests to sign users in, then you'll have to be more careful about redirecting them because, as the message states, you can't render a view over a socket. Technically you could send a bunch of HTML back to the client over a socket, and replace your current page with it, but that's not very good practice. What you can do instead is, in your isAuthenticated policy, check whether the request is happening via sockets (using req.isSocket) and if so, send back a message that the front end can interpret to mean, "you should redirect to the login page now". Something like:
module.exports = function (req, res, next) {
if ([your auth logic here]) {
return next();
}
else {
if (req.isSocket) {
return res.json({status: 403, redirectTo: "/session/new"});
} else {
return res.redirect("/session/new");
}
}
}

How to specify additional action for rest URI

I am working on a gateway project. Several devices gets connected on communication bus of this gateway.
URI '[GET] /devices' gets list of devices.
List of devices is populated by scanning the bus. As scanning is a time consuming operation list is cached in gateway. Normally users access cached information.
But user has an option to get list of devices by forcing a scan. Please suggest me correct REST style representation for scanning. I could think of following options
1) '[GET] /devices/scan'
2) '[GET] /devices' with payload as {"action" : "scan"}
I am not so convinced with option1, as 'scan' is an action, thinking it as a resource is not making sense.
And with option2 I will end up having a payload to parse.
What is the correct way of representing scan scenario?
You can make it a query parameter as in GET /devices?scan=1. You can't have any payload in the content with a GET. You'd have to use a POST.