Cell triangulation on BlackBerry - blackberry

Any ideas about how to do cell triangulation for Blackberry and J2ME phones? I know how to get the cell id but I couldn't do triangulation.

If you can do an HTTP Post to an arbitray website, you can use Google's geolocation api.
Simply POST data in the following JSON format to https://www.google.com/loc/json.
See the above link on how to add more information to your json from wifi etc. to greatly increase the accuracy of the result. And pay special attention to the mobile country code, getting it is not obvious.
{
"version": "1.1.0",
"cell_towers": [
{
"cell_id": "42",
"location_area_code": 415,
"mobile_country_code": 310,
"mobile_network_code.": 410,
"age": 0,
"signal_strength": -60,
"timing_advance": 5555
},
{
"cell_id": "88",
"location_area_code": 415,
"mobile_country_code": 310,
"mobile_network_code": 580,
"age": 0,
"signal_strength": -70,
"timing_advance": 7777
}
]
}
This will return you Google's estimate of the latitude/longitude on your location, along with accuracy and optionally a geocoded address. You can test it quickly e.g. with the Chrome extension called REST Console.
However, it seems that the Blackberry API only provides info on the currently connected cell, not other visible but unregistered cells. In this situation cannot do triangulation, as you (unsuprisingly) need three points to triangulate! However, a less accurate radial estimate of location is still possible.
You can still use the Google API for this, by providing only one tower, or you can use the Ericsson API if you choose. You might want to test with both and compare the accuracy. The Ericcson API is a similar JSON api to Google's, but only expects a single cell as input. A tutorial is available, but it boils down to a JSON request like this:
StringBuffer url = new StringBuffer();
url.append("http://cellid.labs.ericsson.net/json/lookup");
url.append("?cellid=").append(cell.getCellId());
url.append("&mnc=").append(cell.getMnc());
url.append("&mcc=").append(cell.getMcc());
url.append("&lac=").append(cell.getLac());
url.append("&key=").append(API_KEY);
try {
byte[] data = getHttp(url.toString());
if(data!=null) {
JSONObject o = new JSONObject(new String(data));
JSONObject pos = o.getJSONObject("position");
this.longitude = pos.getDouble("longitude");
this.latitude = pos.getDouble("latitude");
this.accuracy = pos.getDouble("accuracy");
this.cellName = pos.optString("name");
}
} catch (IOException e) {
e.printStackTrace();
}

Related

Lora packet data is encoded as hex string but decoding to ASCII is showing nonsense

I am using 2 LHT65N sensors, a Wisgate Edge Lite 2 Gateway, forwarding the payload to a Mosquitto broker, and to display data I am using mqtt.js.
I am receiving packets from the sensors and the data I get is a hex string, but when I am decoding it to plaintext I get no useful data.
So this is the object I get:
{
"applicationID": "1",
"applicationName": "ptxd_temp_humid",
"devEUI": "a84041a777864399",
"deviceName": "sensor_uphill",
"timestamp": 1674051438,
"fCnt": 179,
"fPort": 2,
"data": "CBCF09200203017FFF7FFF",
"data_encode": "hexstring",
"adr": true,
"rxInfo": [
{
"gatewayID": "ac1f09fffe08bf79",
"loRaSNR": 0,
"rssi": -59,
"location": {
"latitude": 0,
"longitude": 0,
"altitude": 0
}
}
],
"txInfo": {
"frequency": 868800000,
"dr": 7
}
You can see that the packet data is encoded as a hex string.
I am using this method:
decoder(bytes: any) {
var batt_v = ((bytes[0]<<8 | bytes[1]) & 0x3FFF)/1000;
var temp_int = ((bytes[2]<<24>>16 | bytes[3])/100).toFixed(2);
var temp_ext = ((bytes[7]<<24>>16 | bytes[8])/100).toFixed(2);
var hum_int = ((bytes[4]<<8 | bytes[5])/10).toFixed(1);
var ext_sen =
{
"0":"No external sensor",
"1":"Temperature Sensor",
}[bytes[6]&0x7F];
return {
Ext_sensor: ext_sen,
BatV: batt_v,
TempC_SHT: temp_int,
Hum_SHT: hum_int,
TempC_DS: temp_ext,
};
To achieve this:
{
"BatV": 1,
"TempC_SHT": "27.56",
"Hum_SHT": "50.6",
"TempC_DS": "25.23"
}
But I get:
{
"BatV": 0,
"TempC_SHT": "0.00",
"Hum_SHT": "0.9",
"TempC_DS": "0.00"
}
I feel that the problem is the gateway. The system log of the gateway is already receiving the encoded data. I tried a hex converter and also the payload formatter of the LHT65N but neither gave me the correct data. I also triple checked the API key, but it is correct.
Is there any configuration that I have to do to receive the correct data?
Solution
I was passing the wrong type into the method. I was confused because I compared my data to others and mine appeared to be too short so I was pretty confused. I am decoding my hexstring to a UInt8Array now and it's working as expected.
client.on('message', (topic, message: Buffer, packet:
mqtt.IPublishPacket) => {
let payload = JSON.parse(message.toString())
console.log(Buffer.from(payload.data, 'hex'))
this.data = this.Decoder(Buffer.from(payload.data, 'hex'));
console.log(this.data)
})
The hex string "data": "CBCF09200203017FFF7FFF" that's received decodes properly with the code you showed. Running it against the hex string, I get:
{
Ext_sensor: 'Temperature Sensor',
BatV: 3.023,
TempC_SHT: '23.36',
Hum_SHT: '51.5',
TempC_DS: '327.67'
}
So that seems to be working. If this arrives via the gateway all the way to the MQTT broker, the problem isn't with the gateway then. It is with either the broker, or the decoder itself, but then again, as I said, the decoder's code seems to be working. It looks like you are getting wrong data, somewhere between it is sent to the decoder and the time it is returned to you.

Twilio Autopilot - How can I receive images from Whatsapp?

I'm building a chatbot with Twilio Autopilot and I want to get the images that I send to the bot, how can I get it? How can I get locations as well?
Thanks a lot.
Twilio developer evangelist here.
There isn't a simple way to do this, but there are a few potential work-arounds. One is to have a webhook endpoint that will get the input and if the payload contains elements of an image, then do whatever you want with it, otherwise if it is just text, then maybe send to Autopilot. That is gone over in this blog post on Autopilot enhancements in Node.js.
Another is to make a Twilio Function that would point to a Twilio Studio flow or Assets if it is media in the first message.
Another is to use Twilio Functions or a similar server. You should have an Autopilot task that redirects to that Function with JSON like this:
{
"actions": [
{
"redirect": {
"uri": "https://REPLACE-WITH-YOUR-FUNCTION-URL.twil.io/auso",
"method": "POST"
}
}
]
}
Then your Twilio Function could get the image URL with something like this in Node.js:
const bodyContent = event.MediaUrl0;
const filename = event.MessageSid + '.png';
Now in a Collect Action you can also specify the Twilio.MEDIA as the type for questions expecting Media and currently we support all media format which are supported by Twilio Messaging.
{
"question": "Please a take a picture of insurance card?",
"name": "insurance_card",
"type": "Twilio.MEDIA",
"validate": {
"allowed_types": {
"list": [
"image/jpeg",
"image/gif",
"image/png",
"image/bmp"
]
},
Lastly, you may be interested in this blog post on building an image classifier with Autopilot and TensorFlow.
Let me know if this helps at all! :D
Regarding images - As seen in this example of an autopilot task program, specify the input type to be an image
{
"actions": [
{
"collect": {
"name": "contact",
"questions": [
{
"question": "Please upload a cool picture of yourself",
"name": "contact_image",
"type": "Twilio.MEDIA"
}
],
"on_complete": {
"redirect": {
"method": "POST",
"uri": "https://url.twil.io/image-processing"
}
}
}
}
]
}
Then you can access the image as seen have done in the following function
exports.handler = function(context, event, callback) {
//we get the Memory from the answered questions.
let memory = JSON.parse(event.Memory);
//set up an array of object "actions" for the autopilot to continue.
let actions = [];
let responseItem;
//print the url of the image
let image_url = memory.twilio.collected_data.contact.answers.contact_image.media.url;
console.log(image_url);
responseItem = {
"redirect": {
"method": "POST",
"uri": "task://next_task"
}
};
actions.push(responseItem);
let respObj = {
"actions": actions
};
callback(null, respObj);
};
Autopilot Troublehooting
Unable to receive picture messages
Autopilot is currently unable to receive messages with pictures or other media types supported by Twilio on any messaging channel and will throw error with code 11200.
I haven't tried WhatsApp location data but there is a blog on the functionality that may help?
New Rich Features Support Deeper Customer Engagement on WhatsApp

Automl image prediction problems

I get different results when using a model to get image annotation predictions from web UI and from API. Specifically, using the web UI I actually get predictions, but using the API I get nothing - just empty output.
It's this one that gives nothing using the API: https://cloud.google.com/vision/automl/docs/predict#automl-nl-example-cli
Specifically, the return value is {} - an empty JS object. So, the call goes through just fine, there's just no output.
Any hints as to how to debug the issue?
By default only results with prediction score > 0.5 are returned by the API.
To get all predictions you will need to provide extra argument 'score_threshold' to predict request:
For the REST API:
{
"payload": {
"image": {
"imageBytes": "YOUR_IMAGE_BYTES"
},
"params": { "score_threshold": "0.0" },
}
}
For the python call:
payload = {'image': {'image_bytes': content }, "params": { "score_threshold": "0.0" }}
With this argument all predictions will be returned. The predictions will be ordered by the 'score'.
Hope that helps,
That doesn't work, at least at the moment.
Instead the params need to go at the same level as the payload. E.g.:
{
"payload": {
"image": {
"imageBytes": "YOUR_IMAGE_BYTES"
}
},
"params": { "score_threshold": "0.0" },
}

Using Google Assistant Change Firebase Database Value

I Created a android app in which if a press a button and value changes in Firebase database (0/1) , i want to do this using google assistant, please help me out, i searched out but didn't found any relevant guide please help me out
The code to do this is fairly straightforward - in your webhook fulfillment you'll need a Firebase database object, which I call fbdb below. In your Intent handler, you'll get a reference to the location you want to change and make the change.
In Javascript, this might look something like this:
app.intent('value.update', conv => {
var newValue = conv.prameters.value;
var ref = fbdb.ref('path/to/value');
return ref.set(newValue)
.then(result => {
return conv.ask(`Ok, I've set it to ${newValue}, what do you want to do now?`);
})
.catch(err => {
console.error( err );
return conv.close('I had a problem with the database. Try again later.');
});
return
});
The real problem you have is what user you want to use to do the update. You can do this with an admin-level connection, which can give you broad access beyond what your security rules allow. Consult the authentication guides and be careful.
I am actually working on a project using Dialogflow webhook and integrated Firebase database. To make this posible you have to use the fulfilment on JSON format ( you cant call firebasedatabase in the way you are doing)
Here is an example to call firebase database and display a simple text on a function.
First you have to take the variable from the json.. its something loike this (on my case, it depends on your Entity Name, in my case it was "tema")
var concepto = request.body.queryResult.parameters.tema;
and then in your function:
'Sample': () => {
db.child(variable).child("DESCRIP").once('value', snap => {
var descript = snap.val(); //firebasedata
let responseToUser = {
"fulfillmentMessages": [
{ //RESPONSE FOR WEB PLATFORM===================================
'platform': 'PLATFORM_UNSPECIFIED',
"text": {
"text": [
"Esta es una respuesta por escritura de PLATFORM_UNSPECIFIED" + descript;
]
},
}
]
}
sendResponse(responseToUser); // Send simple response to user
});
},
these are links to format your json:
Para formatear JSON:
A) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Platform
B) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Message#Text
And finally this is a sample that helped a lot!!
https://www.youtube.com/watch?v=FuKPQJoHJ_g
Nice day!
after searching out i find guide which can help on this :
we need to first create chat bot on dialogflow/ api.pi
Then need to train our bot and need to use webhook as fullfillment in
response.
Now we need to setup firebase-tools for sending reply and doing
changes in firebase database.
At last we need to integrate dialogflow with google assistant using google-actions
Here is my sample code i used :
`var admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
var database = admin.database();
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
exports.hello = functions.https.onRequest((request, response) => {
let params = request.body.result.parameters;
database.ref().set(params);
response.send({
speech: "Light controlled successfully"
});
});`

How to get Youtube channel details using Youtube data API if channel has custom url

I would like to fetch details of a YouTube channel which has a custom URL, like https://www.youtube.com/c/pratiksinhchudasamaisawesome.
Custom channel URLs follow this format: https://www.youtube.com/c/{custom_channel_name}.
I can fetch the details of YouTube channels by Channel ID and username without any issues. Unfortunately, I need to use the custom channel URL which is the only time I encounter this issue.
I developed my app few months ago, and the custom channel URL was working up until a few days ago. Now, the YouTube data API does not return anything for the YouTube custom channel URL if I try get details using their custom name.
To get the details of this channel: https://www.youtube.com/user/thenewboston, for example, the request would be:
GET https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername=thenewboston&key={YOUR_API_KEY}
Response
200
- SHOW HEADERS -
{
"kind": "youtube#channelListResponse",
"etag": "\"zekp1FB4kTkkM-rWc1qIAAt-BWc/8Dz6-vPu69KX3yZxVCT3-M9YWQA\"",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#channel",
"etag": "\"zekp1FB4kTkkM-rWc1qIAAt-BWc/KlQLDlUPRAmACwKt9V8V2yrOfEg\"",
"id": "UCJbPGzawDH1njbqV-D5HqKw",
"snippet": {
"title": "thenewboston",
"description": "Tons of sweet computer related tutorials and some other awesome videos too!",
"publishedAt": "2008-02-04T16:09:31.000Z",
"thumbnails": {
"default": {
"url": "https://yt3.ggpht.com/--n5ELY2uT-U/AAAAAAAAAAI/AAAAAAAAAAA/d9JvaIEpstw/s88-c-k-no-rj-c0xffffff/photo.jpg"
},
"medium": {
"url": "https://yt3.ggpht.com/--n5ELY2uT-U/AAAAAAAAAAI/AAAAAAAAAAA/d9JvaIEpstw/s240-c-k-no-rj-c0xffffff/photo.jpg"
},
"high": {
"url": "https://yt3.ggpht.com/--n5ELY2uT-U/AAAAAAAAAAI/AAAAAAAAAAA/d9JvaIEpstw/s240-c-k-no-rj-c0xffffff/photo.jpg"
}
},
"localized": {
"title": "thenewboston",
"description": "Tons of sweet computer related tutorials and some other awesome videos too!"
}
}
}
]
}
It works perfectly.
Now we have to get details of these channels:
https://www.youtube.com/c/eretteretlenek
https://www.youtube.com/c/annacavalli
Then we get:
GET https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername=annacavalli&key={YOUR_API_KEY}
Response
200
- SHOW HEADERS -
{
"kind": "youtube#channelListResponse",
"etag": "\"zekp1FB4kTkkM-rWc1qIAAt-BWc/TAiG4jjJ-NTZu7gPKn7WGmuaZb8\"",
"pageInfo": {
"totalResults": 0,
"resultsPerPage": 5
},
"items": [
]
}
This can be easily reproduced using the API explorer.
Simplest solution, using API only, is to just use Search:list method of YouTube Data API. From what I can tell (mind you, this is from my own research, official docs say nothing on this subject!), if you search using the custom URL component, with "channel" result type filter and "relevance" (default) sorting, first result should be what you're looking for.
So the following query gets 16 results, with the first one being the one you're looking for. Same goes for all other custom channel URLs I tested, so I think this is the most reliable way of doing this.
GET https://www.googleapis.com/youtube/v3/search?part=id%2Csnippet&q=annacavalli&type=channel&key={YOUR_API_KEY}
The other idea is just scraping YouTube page at the custom URL, where you can find ChannelID in one of the meta tags in HTML code. But that's ineffective, unreliable and AFAIK in violation of YouTube terms of use.
Edit: Well, it returns no results for smaller channels, so it's not reliable at all.
Workaround
Expanding off of #jkondratowicz answer, using the search.list in combination with channels.list you can most of the time resolve the channel from the custom url value.
The channel resource has a property customUrl so if we take the channels from the search.list results and get that extra detail about them from the channels.list it is possible to try and match up the custom url value with the customUrl property.
A working JavaScript method here, just replace the api key with your own. Though it is still not perfect, this tries the first 50 channels returned. More could be done with paging and pageTokens.
function getChannel(customValue, callback) {
const API_KEY = "your_api_key"
$.ajax({
dataType: "json",
type: "GET",
url: "https://www.googleapis.com/youtube/v3/search",
data: {
key: API_KEY,
part: "snippet",
q: customValue,
maxResults: 50,
order: 'relevance',
type: 'channel'
}
}).done(function (res) {
const channelIds = [];
for (let i=0; i<res.items.length; i++) {
channelIds.push(res.items[i].id.channelId);
}
$.ajax({
dataType: "json",
type: "GET",
url: "https://www.googleapis.com/youtube/v3/channels",
data: {
key: API_KEY,
part: "snippet",
id: channelIds.join(","),
maxResults: 50
}
}).done(function (res) {
if (res.items) {
for (let i=0; i<res.items.length; i++) {
const item = res.items[i];
if (item.snippet.hasOwnProperty("customUrl") && customValue.toLowerCase() === item.snippet.customUrl.toLowerCase()) {
callback(item);
}
}
}
}).fail(function (err) {
logger.err(err);
});
}).fail(function (err) {
logger.err(err);
});
}
A good example using it with https://www.youtube.com/c/creatoracademy.
getChannel('creatoracademy', function (channel) {
console.log(channel);
});
However, it is still unreliable as it depends on if the channel comes back in the original search.list query. It seems possible that if the custom channel url is too generic that the actual channel may not come back in the search.list results. Though this method is much more reliable then depending on the first entry of search.list to be the right one as search results don't always come back in the same order.
Issue
There has been at least three feature requests to Google in the past year requesting for an additional parameter for this custom url value but they were all denied as being infeasible. Apparently it is too difficult to implement. It was also mentioned as not being on their roadmap.
https://issuetracker.google.com/issues/174903934 (Dec 2020)
https://issuetracker.google.com/issues/165676622 (Aug 2020)
https://issuetracker.google.com/issues/161718177 (Jul 2020)
Resources
Google: Understand your channel URLs
Search: list | YouTube Data API
Channels: list | YouTube Data API
An alternative way is to use a parser (PHP Simple HTLM DOM parser, for the example below : PHP Simple HTML DOM Parser) :
<?php
$media_url = 'https://www.youtube.com/c/[Channel name]';
$dom = new simple_html_dom();
$html = $dom->load(curl_get($media_url));
if (null !== ($html->find('meta[itemprop=channelId]',0))) {
$channelId = $html->find('meta[itemprop=channelId]',0)->content;
}
?>
(Using Youtube api's "search" method has a quota cost of 100)
It is possible the get the channel ID by the video ID, that can help depends on the need fo your application.
Here are an example:
$queryParams = [
'id' => 'UcDjWCEvZLM'
];
$response = $service->videos->listVideos('snippet', $queryParams)->getItems();
$channelId = $response[0]->snippet['channelId'];
$channelTitle = $response[0]->snippet['channelTitle'];
I'm assuming that only channels with videos uploaded by the channel owner will be of interest. This is accidentally convenient since my method doesn't work with 0 video channels anyway.
Given a channel's url, my method will get the beautifulsoup HTML object of that channel's videos tab, and scrape the HTML to find the unique channel id. It'll then reconstruct everything and give back the channel url with the unique channel id.
your_channel_url = 'Enter your channel url here'
channel_url = your_channel_url.strip("https://").strip("featured")
https = "https://"
channel_vids_tab = https + channel_url + '/videos'
import requests
from bs4 import BeautifulSoup
source = requests.get(channel_vids_tab).text
soup = BeautifulSoup(source, "html.parser")
a = soup.find('body').find('link')['href']
channel_id = a.split('/')[-1]
print(a)
print(channel_id)
This method bypass the headache of one channel having different /user and /c url (for example /user/vechz and /c/vechz vs /c/coreyms and /user/schafer5 leading to the same page). Though you need to manually enter the url at first, it can be easily automated.
I'm also fairly confident that if a channel has 0 videos, this line of thinking can also apply for the playlist created BY the channel owner, and only needs a little tweaking. But if there's 0 videos or playlist created by the channel ... who knows
As #jkondratowicz noted, there is no way to reliably get this from the API as small channels do not return at the top of the search results.
So here is a JS example of how to get the channel id by extracting it from the HTML channel page (h/t #Feign'):
export const getChannelIdForCustomUrl = async (customUrl: string) => {
const page = await axios.get(`https://www.youtube.com/c/${customUrl}`)
const chanId = page.data.match(/channelId":"(.*?)"/)[1]
return chanId
}
Here is the .NET approach to convert custom Channel name/URL to a ChannelId using search API as mentioned in the accepted answer.
// https://www.youtube.com/c/TheQ_original/videos
// they call custom URL ?
// https://stackoverflow.com/questions/37267324/how-to-get-youtube-channel-details-using-youtube-data-api-if-channel-has-custom
// https://developers.google.com/youtube/v3/docs/channels#snippet.customUrl
// GET https://www.googleapis.com/youtube/v3/search?part=id%2Csnippet&q=annacavalli&type=channel&key={YOUR_API_KEY}
//
/// <summary>
/// Returns ChannelID from old "Custom Channel Name/URL"
/// Support the following URLs format
/// https://www.youtube.com/c/MakeYourOWNCreation
/// </summary>
/// <param name="ChannelName"></param>
/// <returns></returns>
// 20220701
public async Task<string> CustomChannelNameToChannelId(String ChannelName)
{
var YoutubeService = YouTubeService();
//
List<YouTubeInfo> VideoInfos = new List<YouTubeInfo>();
//
// -) Step1: Retrieve 1st page of channels info
var SearchListRequest = YoutubeService.Search.List("snippet");
SearchListRequest.Q = ChannelName;
SearchListRequest.Type = "channel";
//
SearchListRequest.MaxResults = 50;
// Call the search.list method to retrieve results matching the specified query term.
var SearchListResponse = await SearchListRequest.ExecuteAsync();
// According to the SO post the custom channel will be the first one
var searchResult = SearchListResponse.Items[0];
//
// Return Channel Information, we care to obtain ChannelID
return searchResult.Id.ChannelId;
}

Resources