node-mango-client to update datasource properties on Mango 2.8
-
Hi,
I want try to use node-mango-client to update some Mango 2.8 datasource properties from outside Mango user interface. Mango instance is running on a RPI3B+.To achieve this I've done the following:
sudo apt install -y nodejs node -v v8.11.1 sudo apt install npm npm -v 1.4.21 (node:4528) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. cd /home/solergy/MANGO/NODE-JS/ npm install mango-client --save (node:2363) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. mango-client@0.4.0 node_modules/mango-client ├── uuid@3.1.0 ├── moment-timezone@0.5.27 └── moment@2.24.0
after this I've tried this little sample:
const MangoClient = require('mango-client'); const client = new MangoClient({ protocol: 'http', host: 'localhost', port: 8810, rejectUnauthorized: false }); const DataPoint = client.DataPoint; const User = client.User; User.login('myUsername', 'myPassword').then(data => { console.log(`Logged in as '${data.username}'.`); return DataPoint.getValue('internal_mango_num_data_points'); }).then(data => { console.log(`There are ${data.value} data points.`); // you can perform any arbitrary rest request like this return client.restRequest({ path: '/rest/v1/data-points/internal_mango_num_data_points', method: 'GET', //data: {object} }); }).then(response => { console.log(`The data point's name is '${response.data.name}'`); });
it is the same descripted here:
https://github.com/infiniteautomation/node-mango-clientbut I've the following error:
solergy@Tracker_0-1:~/MANGO/NODE-JS/node_modules/mango-client $ node example.js (node:4926) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token < in JSON at position 3 at JSON.parse (<anonymous>) at IncomingMessage.response.on (/home/solergy/MANGO/NODE-JS/node_modules/mango-client/src/mangoClient.js:183:62) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickCallback (internal/process/next_tick.js:180:9) (node:4926) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:4926) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
any idea about where's the problem?
-
I took at look at it is because the node client uses the REST V2 APIs to log in and they are not available on Mango 2.8. The actual error is because Mango 2.8 incorrectly returns the HTML error page instead of a JSON error response.
I had a play with manually using
client.restRequest()
to login but that will not work either due to the CSRF protection changing.Otherwise this would work I would think...
const MangoClient = require('@infinite-automation/mango-client'); const client = new MangoClient({ protocol: 'http', host: 'localhost', port: 8080, rejectUnauthorized: false }); const DataPoint = client.DataPoint; const User = client.User; const username = 'admin'; const password = 'admin'; client.restRequest({ path: `/rest/v1/login/${username}`, method: 'POST', params: {password} }).then(response => { const data = response.data; console.log(`Logged in as '${data.username}'.`); return DataPoint.getValue('internal_mango_num_data_points'); }).then(data => { console.log(`There are ${data.value} data points.`); // you can perform any arbitrary rest request like this return client.restRequest({ path: '/rest/v1/data-points/internal_mango_num_data_points', method: 'GET', //data: {object} }); }).then(response => { console.log(`The data point's name is '${response.data.name}'`); });
-
It seems there's still some problem:
solergy@Tracker_0-1:~/MANGO/NODE-JS/node_modules/mango-client $ node example.js (node:3790) UnhandledPromiseRejectionWarning: Error: Mango HTTP error - 403 Forbidden at IncomingMessage.response.on (/home/solergy/MANGO/NODE-JS/node_modules/mango-client/src/mangoClient.js:194:35) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickCallback (internal/process/next_tick.js:180:9) (node:3790) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:3790) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
-
@jared-wiltshire said in node-mango-client to update datasource properties on Mango 2.8:
I had a play with manually using client.restRequest() to login but that will not work either due to the CSRF protection changing.
Otherwise this would work I would think...^ as I said CSRF has changed since 2.8.
-
OK, thanks anyway, I will search for a different approach to change datasource properties from outside Mango 2.8. I've tried to read the blob with the following python script:
#!/usr/bin/python3 import pymysql import json def write_file(data, filename): with open(filename, 'wb') as f: f.write(data) def read_blob(filename): # select photo column of a specific author query = "SELECT data FROM mangoTerlizzi.dataSources where xid='FML01-main'" try: # Open database connection db = pymysql.connect("localhost","user","pwd","mangoTerlizzi" ) # prepare a cursor object using cursor() method cursor = db.cursor() # execute SQL query using execute() method. cursor.execute(query) # Fetch a single row using fetchone() method. data = cursor.fetchone()[0] # write blob data into a file write_file(data, filename) with open(filename) as json_file: data = json.load(json_file) except Error as e: print(e) finally: cursor.close() db.close() read_blob("datasourceDescription.json")
but maybe it is not all the stuff, in fact I've the following error:
solergy@Tracker_0-1:~ $ python3 dbConnection.py Traceback (most recent call last): File "dbConnection.py", line 34, in read_blob data = json.load(json_file) File "/usr/lib/python3.5/json/__init__.py", line 265, in load return loads(fp.read(), File "/usr/lib/python3.5/codecs.py", line 321, in decode (result, consumed) = self._buffer_decode(data, self.errors, final) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xac in position 0: invalid start byte
-
At the end I choose to use a scripting datasource to update datasource properties:
var dsvoMain = com.serotonin.m2m2.db.dao.DataSourceDao.instance.getByXid("FML01-main"); dsvoMain.host = "172.16.0.12"; com.serotonin.m2m2.db.dao.DataSourceDao.instance.saveDataSource(dsvoMain);
and the same for the publisher:
var voPublisher = com.serotonin.m2m2.db.dao.PublisherDao.instance.getByXid("Pub_TRK-0.1") voPublisher.port = "8811"; com.serotonin.m2m2.db.dao.PublisherDao.instance.savePublisher(voPublisher);
but I can't update instead systemSettings,
I've tried with the following:com.serotonin.m2m2.db.dao.SystemSettingsDao.setValue("emailFromName", "Etantonio");
but the result is:
but the method seems to be there in
do you have an idea about where's the problem?
And also, there's a similar way to update excelReport properties on table excelReportTemplates?
Thanks, Antonio
-
@etantonio it looks like you have a syntax error. The other dao classes have a static
instance
member to access the methods but this dao is different in Mango 2.8,The method you are using is not static so you need to first get a reference to the created dao. I believe there is a DaoRegistry class you may be able to use. Just be careful and make sure you understand why some methods are static and others are not.
-
yes, you're right, the following code it's ok. thanks,
var ssdao = new com.serotonin.m2m2.db.dao.SystemSettingsDao(); ssdao.setValue("emailFromName", "Etantonio");
instead for excelReport:
var voExcelReport = com.infiniteautomation.mango.excelreports.dao.ExcelReportTemplateDao.instance.getByXid("My_DailyReport") voExcelReport.setName("Etantonio") com.infiniteautomation.mango.excelreports.dao.ExcelReportTemplateDao.instance.save(voExcelReport);
Antonio