Fetch twin from Azure device sdk - iot

I need to just get the twin of a device using the Azure device sdk for node.js.
I did used the Client clode as below:-
import { Client } from 'azure-iot-device';
import { Mqtt } from 'azure-iot-device-mqtt';
await client.setOptions(options);
await client.open();
const twin = await client.getTwin();
The issue is the twin returned doesn't have the device twin fields but other fields like below:-
{
_events: [Object: null prototype] { newListener: [Function: bound ] },
_eventsCount: 1,
_maxListeners: undefined,
_transport: Mqtt {
_events: [Object: null prototype] {
error: [Function],
connected: [Function],
disconnect: [Array],
message: [Function],
twinDesiredPropertiesUpdate: [Function: bound ]
},
_eventsCount: 5,
_maxListeners: undefined,
_mid: '',
_firstConnection: false,
_authenticationProvider: X509AuthenticationProvider { type: 0, _credentials: [Object] },
_mqtt: MqttBase {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
mqttProvider: [Object],
_onTheWirePublishes: [OnTheWireMessageContainer],
_fsm: [constructor],
_options: [Object],
_config: [Object],
_mqttClient: [MqttClient],
[Symbol(kCapture)]: false
},
_twinClient: MqttTwinClient {
_events: [Object: null prototype],
_eventsCount: 1,
_maxListeners: undefined,
_pendingTwinRequests: {},
_mqtt: [MqttBase],
_topicFsm: [BehavioralFsm],
_responseTopic: [Object],
_desiredPropertiesUpdatesTopic: [Object],
[Symbol(kCapture)]: false
},
_fsm: constructor {
initialState: 'disconnected',
states: [Object],
eventListeners: [Object],
namespace: 'fsm.2',
useSafeEmit: false,
hierarchy: {},
pendingDelegations: {},
_stamped: true,
inputQueue: [],
targetReplayState: 'connected',
state: 'connected',
priorState: 'connecting',
priorAction: 'connected.getTwin',
currentAction: '',
currentActionArgs: undefined,
inExitHandler: false
},
_topicTelemetryPublish: 'devices/amidha/messages/events/',
_topics: { method: [Object], message: [Object] },
_userAgentString: 'azure-iot-device/1.17.1 (node v12.18.0; Ubuntu 18.04; x64)',
[Symbol(kCapture)]: false
},
_retryPolicy: ExponentialBackOffWithJitter {
_errorFilter: DefaultErrorFilter {
ArgumentError: false,
ArgumentOutOfRangeError: false,
DeviceMaximumQueueDepthExceededError: false,
DeviceNotFoundError: false,
FormatError: false,
UnauthorizedError: false,
NotImplementedError: false,
NotConnectedError: true,
IotHubQuotaExceededError: false,
MessageTooLargeError: false,
InternalServerError: true,
ServiceUnavailableError: true,
IotHubNotFoundError: false,
IoTHubSuspendedError: false,
JobNotFoundError: false,
TooManyDevicesError: false,
ThrottlingError: true,
DeviceAlreadyExistsError: false,
DeviceMessageLockLostError: false,
InvalidEtagError: false,
InvalidOperationError: false,
PreconditionFailedError: false,
TimeoutError: true,
BadDeviceResponseError: false,
GatewayTimeoutError: false,
DeviceTimeoutError: false,
TwinRequestError: false
},
immediateFirstRetry: true,
normalParameters: ExponentialBackoffWithJitterParameters {
c: 100,
cMin: 100,
cMax: 10000,
ju: 0.25,
jd: 0.5
},
throttledParameters: ExponentialBackoffWithJitterParameters {
c: 5000,
cMin: 10000,
cMax: 60000,
ju: 0.25,
jd: 0.5
}
},
_maxOperationTimeout: 240000,
desiredPropertiesUpdatesEnabled: false,
properties: {
reported: { update: [Function: update], '$version': 1 },
desired: { '$version': 1 }
},
[Symbol(kCapture)]: false
}
I don't want to listen the twin change events that I can do easily by using above object using twin.on. I need to just get the current twin of the device. Is it possible?

After reading your comments it seems you are expecting some values to be there that just aren't available to the device (when you use the device SDK). The device can read and receive updates on desired properties and read/write to reported properties, the rest is unavailable.
In a comment, you mentioned you want to find the deviceScope in the twin, but that isn't available to the device SDK. You would need the service SDK for that.
When you print the result of const twin = await client.getTwin();, what you see is an object with helper methods to subscribe to desired property changes and patching new reported properties. Like Mark stated in his question, the properties of your twin are included in this object as well.

The current twin is in the JSON you posted. See the section properties:
properties: {
reported: { update: [Function: update], '$version': 1 },
desired: { '$version': 1 }
},
The twin you posted is empty.

Above is not feasible to get the whole twin not just the desired and reported properties from device IoT sdk and that has been confirmed by Azure too. Check here.
The link also has a solution to assign parent child relationship between the leaf and the edge device.

Related

How to use nested maps in Dart?

I am trying to use Dart alongside a api for a school system i have reverse engineered and I'm trying to implement it in a library, when using dio to send a request it is converted to a map (the output of the api is json i think) but it is nested and I’m not sure on how to work with them.
This is the code i have written
class StudentClient{
String sessionID;
StudentClient(this.sessionID);
Future<Map> basicInfo() async {
var dio = Dio();
dio.options.headers["Authorization"] = "Basic $sessionID";
Response loginRequest = await dio.get(
'https://www.classcharts.com/apiv2student/ping',
options: Options(contentType: Headers.formUrlEncodedContentType),
);
assert(loginRequest.data is Map);
Map<dynamic, dynamic> request = loginRequest.data;
return request;
}
and the (censored) output
{success: 1, data: {user: {id: 696969, name: Foo Bar, first_name: Foo, last_name: Bar, avatar_url: https://asdsdsdsd/26.0.0/img/faces/default.png, display_behaviour: true, display_parent_behaviour: false, display_homework: true, display_rewards: true, display_detentions: true, display_report_cards: true, display_classes: false, display_announcements: true, display_attendance: false, display_attendance_type: none, display_attendance_percentage: true, display_activity: true, display_mental_health: false, display_mental_health_no_tracker: false, display_timetable: true, is_disabled: false, display_two_way_communications: true, display_absences: false, can_upload_attachments: false, display_event_badges: false, display_avatars: false, display_concern_submission: false, display_custom_fields: false, pupil_concerns_help_text: , allow_pupils_add_timetable_notes: false, detention_alias_plural_uc: Detentions, announcements_count: 0, messages_count: 0, pusher_channel_name: Pupil_dfghfghhghfghfghfghfghfghfghfghfghfgh, has_birthday: true, has_new_survey: false, survey_id: null}}, meta: {version: 26.0.0}}
Any help would be appreciated!

Error while running "waitForElementVisible" command for Microsoft Edge on nightwatchj.s

When I trying run test in Microsoft edge
browser starting and page is loading, but then I got error :
TypeError: Error while running "waitForElementVisible" command: Error while trying to create HTTP request for "/wd/hub/session/8bf67432a94d18e24f88493fd249c629/element/[object Object]/displayed": Request path contains unescaped characters
For Chrome and Firefox test works fine
Test code
module.exports = {
'Demo test Ecosia.org': function (browser) {
browser
.url('https://www.ecosia.org/')
.waitForElementVisible('body')
.assert.titleContains('Ecosia')
.assert.visible('input[type=search]')
.setValue('input[type=search]', 'nightwatch')
.assert.visible('button[type=submit]')
.click('button[type=submit]')
.assert.containsText('.mainline-results', 'Nightwatch.js')
.end();
}
};
My nightwatch.conf.js
const seleniumServer = require('selenium-server');
const edgeDriver = require('edgedriver');
const chromeDriver = require('chromedriver');
const geckoDriver = require('geckodriver');
module.exports = {
src_folders: ['tests'],
custom_commands_path: '',
custom_assertions_path: '',
page_objects_path: '',
globals_path: '',
live_output: false,
disable_colors: false,
parallel_process_delay: 10,
"test_workers": {
"enabled": false,
"workers": "auto"
},
selenium: {
start_process: true,
//start_session: false,
server_path: seleniumServer.path,
check_process_delay: 5000,
host: '127.0.0.1',
port: 4144,
cli_args: {
"webdriver.ie.driver": ieDriver.path,
"webdriver.chrome.driver": chromeDriver.path,
"webdriver.gecko.driver": geckoDriver.path,
"webdriver.edge.driver": "node_modules/edgedriver_win64/msedgedriver.exe"
}
},
test_settings: {
skip_testcases_on_fail: false,
end_session_on_fail: false,
default: {
desiredCapabilities: {
browserName: 'chrome',
}
},
chrome: {
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true,
chromeOptions: {
w3c: false,
args: ['disable-gpu']
}
}
},
firefox: {
desiredCapabilities: {
browserName: 'firefox',
javascriptEnabled: true,
acceptSslCerts: true,
marionette: true,
}
},
edge: {
desiredCapabilities: {
browserName: 'MicrosoftEdge',
javascriptEnabled: true,
acceptSslCerts: true
}
},
}
};
As you're using the new Edge which is based on chromium, I think you can refer to the same setting of Chrome.
The same error occurs when using Chrome can be fixed by adding "w3c": false. So you could add the following line to fix issue in Edge Chromium:
edgeOptions: { "w3c": false }
Reference link: TypeError ERR_UNESCAPED_CHARACTERS on testing Vue project using Nightwatch

How to configure a non-embedded hasMany relationship with breeze.js

I'm trying to configure a few models with breeze.js
The first is session and I was able to get this working perfectly with a simple query like the below
var query = breeze.EntityQuery.from("sessions").toType("Session");
..but when I tried to add a related "speakers" array to the session I seem to be left with an empty array after the materialization step is complete
Do I need to write a custom json adapter for an api that looks like this?
/api/sessions/
[
{
"id": 1,
"name": "javascript",
"speakers": [
1
]
}
]
/api/speakers/1/
{
"id": 1,
"name": "Toran",
"session": 1
}
Here is my current model configuration (mostly working)
var ds = new breeze.DataService({
serviceName: 'api',
hasServerMetadata: false,
useJsonp: false
});
breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);
this.instance = new breeze.EntityManager({dataService: ds});
this.instance.metadataStore.addEntityType({
shortName: "Speaker",
namespace: "App",
dataProperties: {
id: { dataType: "Int64", isPartOfKey: true },
name: { dataType: "String" },
session: { dataType: "Int64" }
},
navigationProperties: {
session: {
entityTypeName: "Session", isScalar: true,
associationName: "session", foreignKeyNames: ["session"]
}
}
});
this.instance.metadataStore.addEntityType({
shortName: "Session",
namespace: "App",
dataProperties: {
id: { dataType: "Int64", isPartOfKey: true },
name: { dataType: "String" },
speakers: { dataType: "Undefined" }
},
navigationProperties: {
speakers: {
entityTypeName: "Speaker", isScalar: false,
associationName: "speakers", foreignKeyNames: ["speakers"]
}
}
});
Thanks for the help !
note** I'm using ember.js (not backbone/ko/angular)
I tried to keep the above brief but if you need absolutely everything, checkout this single js file
https://github.com/toranb/embereeze/blob/master/website/static/website/js/app.js
update
if I remove the "speakers" dataProperty breeze gets fairly unhappy in this block of code (as it's not a dataProperty on the session model)
var fkProps = fkNames.map(function (fkName) {
//fkName is speakers .... yet it's not a data property so bad things happen :(
return parentEntityType.getDataProperty(fkName);
});
var fkPropCollection = parentEntityType.foreignKeyProperties;
// Array.prototype.push.apply(parentEntityType.foreignKeyProperties, fkProps);
fkProps.forEach(function (dp) {
I just did a PR - the association name should be the same on both ends, much like any relational database would have.
this.instance.metadataStore.addEntityType({
shortName: "Speaker",
namespace: "App",
dataProperties: {
id: { dataType: "Int64", isPartOfKey: true },
name: { dataType: "String" },
session: { dataType: "Int64" }
},
navigationProperties: {
sessionModel: {
entityTypeName: "Session", isScalar: true,
associationName: "Speaker_Sessions", foreignKeyNames: ["session"]
}
}
});
this.instance.metadataStore.addEntityType({
shortName: "Session",
namespace: "App",
dataProperties: {
id: { dataType: "Int64", isPartOfKey: true },
name: { dataType: "String" }
},
navigationProperties: {
speakers: {
entityTypeName: "Speaker", isScalar: false,
associationName: "Speaker_Sessions"
}
}
});
So I renamed the association, removed the extra speakers property on the Session (there is no property for the relationship, simply an inverse that should be mapped) and then removed the foreign key on the session as you don't need one there. By assigning passing session down from the API with the models shown above should be enough to let Breeze know
Speakers' have a session property, which is a foreign key pointing to a single session.
Sessions have a collection of speakers, which should be mapped on the other end

D2L How to create forum topic using Rest API?

Using D2L Rest API Sending following block for creating topic inside already existing forum:
URL: POST /d2l/api/le/(D2LVERSION: version)/(D2LID: orgUnitId)/discussions/forums/(D2LID: forumId)/topics/
{
"Name" : "Test Forum API",
"Description" : {
"Text" : "",
"Html" : "Test"
},
"AllowAnonymousPosts" : true,
"StartDate" : null,
"EndDate" : null,
"IsHidden" : false,
"UnlockStartDate" : null,
"UnlockEndDate" : null,
"RequiresApproval" : false,
"ScoreOutOf" : null,
"IsAutoScore" : true,
"IncludeNonScoredValues" : true,
"ScoringType" : null,
"IsLocked" : false,
"MustPostToParticipate" : true
}
Getting error:
INFO: Redirect requested but followRedirects is disabled
Status Code 302 Object moved to /d2l/error/404
Post and Redirect don't work together. Often environments (a loadbalancer or other network component) will automatically redirect all http operations to https. Then your client library won't actually follow the 302.
You probably want to use https if it is enabled, and you can make the D2L Libraries produce https urls.
(You may also want to have your client http library you are using follow redirects though because there are scenarios where the GET operations might get redirected)
Note that the CreateTopicData structure that you must pass the API to create a new topic does not use a RichText composite structure for the Description property on input. Instead, you must use a RichTextInput composite structure, which is slightly different:
{
"Name" : "Test Forum API",
"Description" : {
"Content" : "Test",
"Type": "HTML"
},
...
}
The API will pass back a RichText structure on output, however.
Using our test service, with a POST to an URL like this (assuming an org ID of 8083, and a forum ID of 4174)
https://myLMShost.edu/d2l/api/le/1.0/8083/discussions/forums/4174/topics/
we passed in a JSON structure that looks like this:
{'AllowAnonymousPosts': True,
'Description': {'Content': 'test', 'Type': 'HTML'},
'EndDate': None,
'IncludeNonScoredValues': False,
'IsAutoScore': True,
'IsHidden': False,
'IsLocked': False,
'MustPostToParticipate': True,
'Name': 'Test Forum API',
'RequiresApproval': False,
'ScoreOutOf': None,
'ScoringType': None,
'StartDate': None,
'UnlockEndDate': None,
'UnlockStartDate': None}
And our test service returned the new topic post, like this:
{'AllowAnonymousPosts': True,
'Description': {'Html': 'test', 'Text': ''},
'EndDate': None,
'ForumId': 4174,
'IncludeNonScoredValues': False,
'IsAutoScore': True,
'IsHidden': False,
'IsLocked': False,
'MustPostToParticipate': True,
'Name': 'Test Forum API',
'PinnedPostCount': 0,
'RatingsCount': 0,
'RatingsSum': 0,
'RequiresApproval': False,
'ScoreOutOf': None,
'ScoredCount': 0,
'ScoringType': None,
'StartDate': None,
'TopicId': 88569,
'UnapprovedPostCount': 0,
'UnlockEndDate': None,
'UnlockStartDate': None}

Why is my geo coordinate always false?

I'm sending a tweet to #JoeMaxiTaxis from my Android phone. The trouble is, the coordinates simply do not show up.
I double checked that GPS is enabled and that location is enabled on the Twitter app.
Here is the response I get on the server:
{ in_reply_to_status_id_str: null,
contributors: null,
place: null,
in_reply_to_screen_name: 'JoeMaxiTaxis',
text: '#joemaxitaxis lll',
favorited: false,
in_reply_to_user_id_str: '634579476',
coordinates: null,
geo: null,
retweet_count: 0,
created_at: 'Fri Jul 13 22:13:01 +0000 2012',
source: 'Twitter for Android',
in_reply_to_user_id: 634579476,
in_reply_to_status_id: null,
retweeted: false,
id_str: '223902880527167488',
truncated: false,
user:
{ favourites_count: 0,
friends_count: 0,
profile_background_color: 'C0DEED',
following: null,
profile_background_tile: false,
profile_background_image_url_https: 'https://si0.twimg.com/images/themes/theme1/bg.png',
followers_count: 0,
profile_image_url: 'http://a0.twimg.com/sticky/default_profile_images/default_profile_0_normal.png',
contributors_enabled: false,
geo_enabled: true,
created_at: 'Wed Jul 07 16:19:53 +0000 2010',
profile_sidebar_fill_color: 'DDEEF6',
description: '',
listed_count: 0,
follow_request_sent: null,
time_zone: 'Dublin',
url: null,
verified: false,
profile_sidebar_border_color: 'C0DEED',
default_profile: true,
show_all_inline_media: false,
is_translator: false,
notifications: null,
profile_use_background_image: true,
protected: false,
profile_image_url_https: 'https://si0.twimg.com/sticky/default_profile_images/default_profile_0_normal.png',
location: 'Dublin, Ireland',
id_str: '163924257',
profile_text_color: '333333',
name: 'Eamonn Hynes',
statuses_count: 6,
profile_background_image_url: 'http://a0.twimg.com/images/themes/theme1/bg.png',
id: 163924257,
default_profile_image: true,
lang: 'en',
utc_offset: 0,
profile_link_color: '0084B4',
screen_name: 'rainbowcabs' },
id: 223902880527167500,
entities: { user_mentions: [ [Object] ], urls: [], hashtags: [] } }
Can anyone offer any insight?
Does your HTTP request get the long and the lat parameters that contains your GPS coordinates (longitude and latitude) ? Whatever your app does with the GPS, if Twitter does not got both long and lat parameters and if you are not "geo enabled", Twitter will not be able to return you the location with the rest of the written tweet.

Resources