Archive

Archive for May, 2019

Co2 emissions database available via #EEA

co2

If you are looking for environmental data on vehicles, to judge their impact on the environment, then this dataset available from the EEA has a record of millions of european vehicles, and their CO2 footprint.

It’s available for download here; https://payhip.com/b/Jclb

Categories: Uncategorized

Using JsonReaderWriterFactory. CreateJsonReader in C#

screen-shot-2017-04-17-at-114949-am

Whenever you want to read JSON in C#, I don’t normally look any further than Newtonsoft.Json , but if you are not allowed to use third-party libraries in your project, then there is a little known JSON parser built into .NET (or the System.Runtime.Serialization.Json library).

But, it’s not nice to use, and who wants to use XPath Queries with Json anyway, it’s awkward and unnatural!

So, I’ve written a class that does not use any third-party libraries, but uses a similar calling structure to Newtonsoft.JSON.

using System.Collections.Generic;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml.Linq;

namespace Synergy.Common
{
/// <summary>
/// A simplified version of JSON
/// </summary>
public class MyJson : Dictionary<string, MyJson>
{
/// <summary>
/// The value of the node
/// </summary>
public string Value;

// public Dictionary<string, MyJson> Children = new Dictionary<string, MyJson>();

/// <summary>
/// Parses the specified json.
/// </summary>
/// <param name=”json”>The json.</param>
/// <returns></returns>
public static MyJson Parse(string json)
{
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(json), new System.Xml.XmlDictionaryReaderQuotas());
var xe = XElement.Load(jsonReader);
return FromElement(xe);
}

private static MyJson FromElement(XContainer xe)
{
var root = new MyJson { Value = “” };
foreach (var element in xe.Elements())
{
if (root.ContainsKey(element.Name.LocalName)) continue; // Don’t support duplicates so far
root.Add(element.Name.LocalName,
element.HasElements ? FromElement(element) : new MyJson {Value = element.Value});
}
return root;
}
}
}

You call MyJson.Parse() passing in some JSON, and what you get back, is a nested dictionary, where each dictionary entry can have sub-dictionaries. If it has an empty sub-dictionary, then it will have a Value property set.

The Value property is always a string, so there is no fancy date or number parsing yet, and it does not allow duplicate keys.

Feel free to comment with improvements.

Categories: Uncategorized

Get language codes from a country code in C#

Language-Families-World-Map

Given a country code – i.e. BE (Belgium), you might want to know the most commonly spoken languages in that country – i.e FR and NL (French and Dutch), here’s some code to do that in C#, without a database lookup.

private static IEnumerable<string> GetLanguagesSpokenInCountry(string country)
{
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
var languagesSpoken = allCultures.Where(c =>
{
if (c.IsNeutralCulture) return false;
if (c.LCID == 0x7F) return false; // Ignore Invariant culture
var region = new RegionInfo(c.LCID);
return region.TwoLetterISORegionName == country;
}).Select(c => c.TwoLetterISOLanguageName.ToUpper()).ToList();
return languagesSpoken;
}

You might be surprised that India (IN) returns 19 languages! – on my PC.

Categories: Uncategorized

Cloud Answering Machine #app just re-launched for #android

Cloud Answering Machine is a service where you can get a second phone number hosted virtually online, that allows you to recieve voicemail and SMS messages, without requiring another physical phone, or physical phone line. What’s more, you can create a phone number anywhere in the world, so you can give the impression that your buisness is based in New York, when you really live in the UK.

The main use for a second phone line is to separate high importance calls from your work or family, from low importance calls from people who don’t need to be dealt with urgently. Perhaps separating calls from your sideline business and your day job, or even to create a phone number for purposes that you don’t want your wife or boss knowning about.

We’ve recently relaunched our app based on a purely Native platform, rather than the old Cordova based version at https://play.google.com/store/apps/details?id=com.record.recordingapp

Please feel free to download it – it’s free!, and please give us a good rating if you like it.

We’ve also open sourced it, so it’s free for you to build upon, or create your own companion apps for this. Check out the repo on Github: https://github.com/infiniteloopltd/CloudAnsweringMachineAndroid

Categories: Uncategorized

Translate #RESX files online for #free

resx

https://www.resxtranslate.com/  is a website that allows you upload .NET RESX files or Resource files, and have them translated into one of 25 languages automatically, and for free.

You upload the RESX file, enter in your email address, the language pair required, and the translation quality level. It then emails you back the translated RESX file in seconds (or minutes, depending on the size).

The automatic translation is powered by Yandex translate, which offers a translation API, which is called via a simple API as follows;

var strUrl = “https://translate.yandex.net/api/v1.5/tr.json/translate?&#8221;;
strUrl += “key=trnsl….”;
strUrl += “&text=” + text;
strUrl += “&lang=” + language;
var wc = new WebClient { Encoding = Encoding.UTF8 };
var strJson = wc.DownloadString(strUrl);
var jTranslate = JObject.Parse(strJson);
var strEnglish = jTranslate[“text”].First.ToString();
return strEnglish;

 

Categories: Uncategorized

Convert #3gp to #wav in c# using #ffmpeg

3gp

I recently found today that Android’s native audio recording format is 3GP ( 3rd Generation Partnership Project ), which may need to be decoded to a decompressed raw format like WAV before you do certain processing on it. My first google searches led me to Alvas, which seemed good, but their trial version has a nag screen that would break IIS, and I didn’t want to pay.

So, I turned to FFMPEG, a free tool, that’s typically used for Video conversion, but also works on audio. The command from the CLI is

ffmpeg -i bible.3gp bible.wav

Which generates the following dump of data;

ffmpeg version N-93863-g58d167bcd5 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 8.3.1 (GCC) 20190414
configuration: –enable-gpl –enable-version3 –enable-sdl2 –enable-fontconfig –enable-gnutls –enable-iconv –enable-libass –enable-libdav1d –enable-libbluray –enable-libfreetype –enable-libmp3lame –enable-libopencore-amrnb –enable-libopencore-amrwb –enable-libopenjpeg –enable-libopus –enable-libshine –enable-libsnappy –enable-libsoxr –enable-libtheora –enable-libtwolame –enable-libvpx –enable-libwavpack –enable-libwebp –enable-libx264 –enable-libx265 –enable-libxml2 –enable-libzimg –enable-lzma –enable-zlib –enable-gmp –enable-libvidstab –enable-libvorbis –enable-libvo-amrwbenc –enable-libmysofa –enable-libspeex –enable-libxvid –enable-libaom –enable-libmfx –enable-amf –enable-ffnvcodec –enable-cuvid –enable-d3d11va –enable-nvenc –enable-nvdec –enable-dxva2 –enable-avisynth –enable-libopenmpt
libavutil 56. 27.100 / 56. 27.100
libavcodec 58. 52.101 / 58. 52.101
libavformat 58. 27.103 / 58. 27.103
libavdevice 58. 7.100 / 58. 7.100
libavfilter 7. 53.100 / 7. 53.100
libswscale 5. 4.101 / 5. 4.101
libswresample 3. 4.100 / 3. 4.100
libpostproc 55. 4.100 / 55. 4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘bible.3gp’:
Metadata:
major_brand : 3gp6
minor_version : 256
compatible_brands: isom3gp6
creation_time : 2015-07-24T19:40:33.000000Z
Duration: 00:04:03.30, start: 0.000000, bitrate: 229 kb/s
Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 320×180 [SAR 1:1 DAR 16:9], 193 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 30k tbc (default)
Metadata:
creation_time : 2015-07-24T19:40:33.000000Z
handler_name : IsoMedia File Produced by Google, 5-11-2011
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 22050 Hz, mono, fltp, 32 kb/s (default)
Metadata:
creation_time : 2015-07-24T19:40:33.000000Z
handler_name : IsoMedia File Produced by Google, 5-11-2011
Stream mapping:
Stream #0:1 -> #0:0 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, wav, to ‘bible.wav’:
Metadata:
major_brand : 3gp6
minor_version : 256
compatible_brands: isom3gp6
ISFT : Lavf58.27.103
Stream #0:0(eng): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 22050 Hz, mono, s16, 352 kb/s (default)
Metadata:
creation_time : 2015-07-24T19:40:33.000000Z
handler_name : IsoMedia File Produced by Google, 5-11-2011
encoder : Lavc58.52.101 pcm_s16le
size= 10478kB time=00:04:03.29 bitrate= 352.8kbits/s speed=22.7x
video:0kB audio:10478kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000727%

To, write the same code in C# it’s

Process p = new Process
{
StartInfo =
{
FileName = @”D:\Research\ffmpeg.exe”,
Arguments = @”-i d:\research\bible.3gp d:\research\bible.wav”,
WindowStyle = ProcessWindowStyle.Hidden,
RedirectStandardOutput = true,
UseShellExecute = false
}
};
p.Start();
p.WaitForExit();

.. And yes, I’m using a file called bible.3gp, not that I’m in any way religious, it was just the first 3gp file I could find online.

This code also works in a ASP.NET page, hosted by IIS, without elevated privileges.

FYI, this code is going to be used in an upcomming Android app for www.cloudansweringmachine.com

Categories: Uncategorized

Simple #logging in C#

6I3oEOP4

If you have some software in C# that runs unattended, or doesn’t have a graphical interface, then hunting down problems with it, can be a pain, and a simple text logger comes to the rescue.  – So at least you can check a log file to see what went wrong.

Writing a text logger isn’t complicated, in fact, it’s probably only a handful of lines of code, but it’s not something that a client or your boss is going to pay you for, it’s just a diagnostic tool, that adds nothing to the end user experience. So, it needs to be super-simple to add and use.

My favourite, so far is SimpleLogger, which you can install via nuget here;

Install-Package SimpleLogger

Then to use it, you firstly configure it as follows;

Logger.LoggerHandlerManager
.AddHandler(new ConsoleLoggerHandler())
.AddHandler(new FileLoggerHandler())
.AddHandler(new DebugConsoleLoggerHandler());

Then write out your progress as follows;

Logger.Log(strProgress);

And it outputs to the console, and to a file, which is date stamped, so you can look back over it.

The only downside is, that I guess there is no limit to the log file sizes, I’m not sure how to do cleanup, in case you write too much to the file. – And I did notice, that if you call this in a multi-threaded environment, if you get a collision (two logs at once), the logger will crash.

Anyway, top marks for simplicity!

Categories: Uncategorized

Access #EventBrite API to display event information

eventbrite-750

If you’re creating a What’s On guide, or need to supplement one with existing events, then the EventBrite API is free, and is easy to use. Here is an example below using NodeJS and the Request NPM package.

First, off, you need to authenticate with a Bearer Token, this is easy to do, but you’ll need to get one from the Developer portal on Eventbrite. Here’s some NODE code that makes an authenticated request against the Eventbrite API

function EventbriteRequest(strUrl, callback)
{

request(
{
uri: strUrl,
headers:
{
‘Content-Type’: ‘application/json’
},
auth: {
bearer: ‘xxxxxxxx’
}
}, function (error, response, body) {
console.log(‘error:’, error);
console.log(body);
if (error == null)
{
var jBody = JSON.parse(body);
callback(jBody,null);
}
else
{
callback(null,error);
}
});
}

This simply takes an eventbrite URL, and a callback, which will contain the response in the first parameter, or null, and an error in the second parameter.

And to make a “Whats On” type search, you simply call the following

var strUrl = “https://www.eventbriteapi.com/v3/events/search?&#8221;;
strUrl += “q=” + search;
strUrl += “&location.address=northern+ireland”;
console.log(strUrl);
EventbriteRequest(strUrl, function(response, error)
{

….

This is taken from an Alexa app, but retired as a feature for other reasons.

Categories: Uncategorized

Access #UK government #database of food establishments

share-default

If you’re developing an app or software that lists places to eat in the UK, it’s great to have a definitive database of every official food vending establishment in the UK, and Food.gov.uk provides this. The API is free, and doesn’t even require authentication. Here’s a sample

https://ratings.food.gov.uk/search-address/belfast/rating/1/100/json

Here’s the official docs

Click to access api-guidance.pdf

And here’s some NodeJS code that I wrote to parse this; (It’s taken from an Alexa app)

module.exports.List = function(city, callback) {

var response = “”;
var strUrl = “https://ratings.food.gov.uk/search-address/&#8221; + city + “/rating/1/100/json”;
request(strUrl, function (error, response, body) {
console.log(‘error:’, error); // Print the error if one occurred
console.log(body);
if (error == null)
{
var jBody = JSON.parse(body);
if (typeof jBody.FHRSEstablishment.EstablishmentCollection == “undefined”)
{
response = text.dyn().RESTAURANT_NONE
.replace(“{city}”, city );
callback(response);
return;
}
// Filter
var restaurants = jBody.FHRSEstablishment.EstablishmentCollection.EstablishmentDetail.filter(function(el){
return ( (el.PostCode || “”).indexOf(“BT”) == 0
&& el.BusinessTypeID == 1
&& el.AddressLine3.toLowerCase() == city.toLowerCase()
);
});
if (restaurants.length == 0)
{
response = text.dyn().RESTAURANT_NONE
.replace(“{city}”, city );
callback(response);
return;
}
var restaurantList = [];
restaurants.forEach(function(element){
restaurantList.push(element.BusinessName);
});
var strRestaurantList = customJoin(restaurantList, ” , “, ” ” + text.dyn().AND + ” ” );

response = text.dyn().RESTAURANT_LIST
.replace(“{city}”, city )
.replace(“{restaurantList}”, strRestaurantList );
callback(response);
}
});
};

function customJoin(arr,s1,s2){
return(arr.slice(0,-1).join(s1).concat(arr.length > 1 ? s2 : ”, arr.slice(-1)));
}

Hope this is useful to somebody!

Categories: Uncategorized

Find #Twitter #Influencers in your area, using #linqtotwitter

twitter

If you are promoting a product or service that is relevant only to a certain geographic area, i.e. a cafe or restaurant, then you might want to reach out to local twitter influencers – that is, people that carry alot of followers, and some might be amenable to tweet about your restaurant in return for a free meal.

Check out the demo at http://twitter.derrycreativescollective.com/

Or, if you’re a c# developer, and don’t need the use-case spelled out to you, then read on…

Here, I’ve used Linq2Twitter, which is FAR more stable than Tweetsharp, even though I do find the linq syntax a bit back-to-front.

It’s installed via Nuget as follows

Install-Package linqtotwitter

Now, What I’ve done, is created a web form page that returns JSON, which will be consumed by an ajax call. The call takes a strGeo parameter, which effectively is LAT,LON,RADIUS where radius, I’ve hard-coded to 10mi (10 miles)

You’ll need a Twitter developer account, and an App set up to get your authentication details, and you can’t use mine .. so they are excluded from the example below;

var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore
{
ConsumerKey = “…”,
ConsumerSecret = “…”,
OAuthToken = “….”,
OAuthTokenSecret = “…”
},
};
var twitterCtx = new TwitterContext(auth);
Search(twitterCtx, strGeo);

And the search method is as follows

void Search(TwitterContext twitterCtx, string geo)
{
var searchResponse =
(from search in twitterCtx.Search
where search.Type == SearchType.Search &&
search.Query == “a” &&
search.GeoCode == geo &&
search.Count == 100

select search)
.FirstOrDefault();

if (searchResponse.Statuses.Count == 0)
{
return;
}

if (searchResponse != null && searchResponse.Statuses != null)
{
var users = searchResponse.Statuses.Select(s =>
s.User).GroupBy(u =>
u.ScreenNameResponse).Select(g =>
g.FirstOrDefault()).OrderByDescending(u =>
u.FollowersCount).ToArray();
var jsSerializer = new JavaScriptSerializer();
var strJson = jsSerializer.Serialize(users);
Response.AppendHeader(“Access-Control-Allow-Origin”, “*”);
Response.Headers.Add(“Content-type”, “text/json”);
Response.Write(strJson);
}
}

This, searches a given geographic area for tweets, and grabs 100 of them. It then takes all the users that posted the tweets, removes duplicates, and orders by follower count. It then spits the lot out as JSON, with a CORS header added.

On the web side, I use Google to reverse geocode the city typed by the user, to get a lat / lon, using the following code

var address = $(“#tbLocation”).val();
geocoder.geocode({ ‘address’: address }, function (results, status) {
if (status === ‘OK’) {
var geoResult = results[0].geometry.location;
var strGeo = geoResult.lat() + “,” + geoResult.lng() + “,10mi”;
callAPI(strGeo);
} else {
alert(‘Geocode was not successful for the following reason: ‘ + status);
}
});

And, then I have defined callAPI as follows;

function callAPI(geo) {
console.log(“searching: ” + geo);
$.getJSON(“/PopularAjax.aspx?geo=” + geo,
function (data) {
$(“#btnSearch”).removeClass(“disabled”);
var tpl = $(“#tplItem”).html();
var strHtml = Mustache.render(tpl, data);
$(“#divResults”).html(strHtml);
});
}

Where I take the raw JSON returned by the AJAX and render it against a Mustache template, which is then injected into a Bootrap-based page.

Quite simple, but hopefully, it is useful to someone.

 

Categories: Uncategorized