flutter/dart connect to Azure via mqtts - flutter

I am trying to connect to our MQTT server on Azure.
I use MQTTBox as our testbed, and it is successfully connecting to
protocol: mqtts
host: .azure-devices.net/$iothub/websocket
user: .azure-devices.net/testdevice/?api-version=2018-06-30
password: 'SharedAccessSignature sr=.azure-devices.net%2Fdevices%2Ftestdevice&sig=xxxxxxx'
I tried the mqtt_client library, which was an issue with "$" sign in the server endpoint and throws ""SocketException: Failed host lookup: 'mqttQueue.azure-devices.net/$iothub/websocket' (OS Error: No address associated with hostname, errno = 7)"
final client = MqttServerClient('<hubname>.azure-devices.net/\$iothub/websocket', '');
client.port = 8883;
client.secure = true;
final connMess = MqttConnectMessage()
.authenticateAs('<hubname>.azure-devices.net/testdevice/?api-version=2018-06-30',
'SharedAccessSignature sr=<hubname>.azure-devices.net%2Fdevices%2Ftestdevice&sig=xxxxxxx')
.withClientIdentifier('testdevice')
.withWillTopic('devices/testdevice/messages/events/') // If you set this you must set a will message
.withWillMessage('My Will message')
.startClean() // Non persistent session for testing
.withWillQos(MqttQos.atLeastOnce);
client.connectionMessage = connMess;
try {
await client.connect();
}
I also tried unsuccessfully
final client = MqttServerClient('HostName=<hubname>.azure-devices.net;DeviceId=testDevice;SharedAccessKey=m....Y=','')
Any working example to Azure in dart/flutter is appreciated, as I fail to map the Azure given parameters to the parameters in the library.

final client = MqttServerClient('<hubname>.azure-devices.net', '');
client.useWebSocket = false;
client.port = 8883;
client.autoReconnect = true;
client.keepAlivePeriod = 3600;
final String user = '<hubname>.azure-devices.net/<your device id>';
late String password; // <== password string is obtained elsewhere
final connMess = MqttConnectMessage()
.withClientIdentifier(clientIdentifier)
.startClean();
client.connectionMessage = connMess;
client.connect(username, password);

Related

How can i use Metamask to make transactions?

import 'package:http/http.dart'; //You can also import the browser version
import 'package:web3dart/web3dart.dart';
var apiUrl = "http://localhost:7545"; //Replace with your API
var httpClient = Client();
var ethClient = Web3Client(apiUrl, httpClient);
var credentials = ethClient.credentialsFromPrivateKey("0x...");
// You can now call rpc methods. This one will query the amount of Ether you own
EtherAmount balance = ethClient.getBalance(credentials.address);
print(balance.getValueInUnit(EtherUnit.ether));
This is the code from web3dart package in flutter. I want to replace the apiUrl with some kinds of url from the Metamask mobile app itself(connected via walletConnect package). Any help guys?
You can use this method for connect to rpc final credentials = EthPrivateKey.fromHex(privatekey); because the other is deprecated.
print("Accediendo al servidor blockchain...");
var rpcUrl = "HTTP://127.0.0.1:8545";
const String privatekey = "2812d889332dce9256c385355839102910ae8cc1c16c6e1212174d1dc91d9738";
final client = Web3Client(rpcUrl, Client());
final credentials = EthPrivateKey.fromHex(privatekey);
final address = credentials.address;
print(address.hexEip55);
Use this package for Flutter. LINK: https://pub.dev/packages/web3dart
var apiUrl = "http://localhost:7545"; //Replace with your API
var httpClient = new Client();
var ethClient = Web3Client(apiUrl, httpClient);
EthPrivateKey credentials = await ethClient.credentialsFromPrivateKey("0x...........");
EthereumAddress address=credentials.address;
print("ADDRESS FORM PRIVATE KEY : "+address.hex);

Inspect WebSocket packages with Charles proxy in Flutter app

I'm developing mobile application using Flutter/Dart. What I need is to debug/test my application's network traffic with Charles proxy/Fiddler. It's easy to inspect http requests/responses in dart/flutter using Charles proxy. We only need to tell HttpClient an address of proxy server (IP address of machine where Charles is installed) like this:
final client = HttpClient();
client.findProxy = (uri) {
String proxy = '1.2.3.4:8888';
return "PROXY $proxy;";
};
client.badCertificateCallback =
((X509Certificate cert, String host, int port) => Platform.isAndroid);
But how can I debug WebSocket traffic created via
WebSocket.connect('wss://server_address');? WebSocket doesn't have any api for setting proxy settings and I couldn't find anything on forums.
That being said, I already did such things in the past in another mobile app written on C# and it was pretty easy.
Figured it out. There are actually multiple ways to do that:
Global Proxy settings:
class ProxiedHttpOverrides extends HttpOverrides {
String _proxy;
ProxiedHttpOverrides(this. _proxy);
#override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..findProxy = (uri) {
return _proxy.isNotEmpty ? "PROXY $_proxy;" : 'DIRECT';
}
..badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
}
}
void main() {
String proxy = '1.2.3.4:8888';
HttpOverrides.global = new ProxiedHttpOverrides(proxy);
runApp(MyApp());
}
Custom HttpClient passed into WebSocket.connect
HttpClient client = HttpClient();
client.findProxy = (uri) => "PROXY $proxy;";
client.badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
WebSocket.connect(url, customClient: client);
Manual way: We need to upgrade to WebSocket using simple HttpClient with specified proxy settings. In that case we will be able to inspect WebSocket traffic in Charles/Fiddler.
Future<WebSocket> createProxySocket() async {
String url = 'https://echo.websocket.org:443';//address must start from http(s)://, not from ws(s)://, as we are connecting using http
String proxy = '1.2.3.4:8888';//your machine address (or localhost if debugging on the same machine)
Random r = new Random();
String key = base64.encode(List<int>.generate(8, (_) => r.nextInt(255)));
HttpClient client = HttpClient();
client.findProxy = (uri) => "PROXY $proxy;";
client.badCertificateCallback = (X509Certificate cert, String host, int port) => Platform.isAndroid;
Uri uri = Uri.parse(url);
HttpClientRequest request = await client.getUrl(uri);
request.headers.add('Connection', 'upgrade');
request.headers.add('Upgrade', 'websocket');
request.headers.add('Sec-WebSocket-Version', '13');
request.headers.add('Sec-WebSocket-Key', key);
HttpClientResponse response = await request.close();
Socket socket = await response.detachSocket();
return WebSocket.fromUpgradedSocket(socket, serverSide: false);
}

How to use proxies library in flutter?

I want to create an Android app that connects to a proxy by button clicked and I'd like to know what should do to make this event?
My proxy needs(password, username, host, port).
I would be appreciated if you help me with this problem .
Add DIO settings like this
String proxy = '<IP>:<PORT>'; //eg 192.168.1.1:8080
var credentials = HttpClientBasicCredentials(<USERNAME>, <PASSWORD>);
bool isProxyChecked = true;
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
client.badCertificateCallback = (X509Certificate cert, String host, int port) {
return isProxyChecked && Platform.isAndroid;
};
client.findProxy = (url) {
return isProxyChecked ? 'PROXY $proxy' : 'DIRECT';
};
client.addProxyCredentials(<PROXY_IP>, <PORT>, 'main', credentials);
};

MQTT certificate-based authentication in flutter web and mobile

I am trying to use MQTT in a Flutter project to test the prototype. And I am using custom certificate-based authentication.
I am using mqtt_client package.
before connect SecurityContext giving this error in web Unsupported operation: default SecurityContext getter
below is my sample code
try {
SecurityContext securityContext =
SecurityContext(withTrustedRoots: false);
securityContext.setTrustedCertificatesBytes(caCertificate);
securityContext.useCertificateChainBytes(caCertificate);
securityContext.setClientAuthoritiesBytes(clientCertificate,
password: String.fromCharCodes(privateKey));
} catch (e) {
print(e);
}
_client = MqttClient('m.test.com', _identifier);
_client.port = 8883;
_client.keepAlivePeriod = 20;
_client.onDisconnected = onDisconnected;
_client.secure = true;
//_client.securityContext = securityContext;
_client.onBadCertificate = ((X509Certificate cert) => false);
_client.logging(on: true);```
this worked for me but I don't understand what (dynamic a) is doing ... perhaps someone can explain it in more detail ?
void initializeMQTTClient() async {
_client = MqttServerClient(_host, _identifier);
_client.port = 8883; //1883
_client.keepAlivePeriod = 20;
_client.onDisconnected = onDisconnected;
_client.secure = true; // false
_client.logging(on: true);
_client.securityContext = SecurityContext.defaultContext;
// _client.useWebSocket = false;
/// Add the successful connection callback
_client.onConnected = onConnected;
_client.onSubscribed = onSubscribed;
_client.onBadCertificate = (dynamic a) => true;

How to Access using Xamarin.Forms local Web API with Emulator for Visual Studio?

I've created .NET Framework API which contains authentication, I launch the Web API using Jetbrains Rider and I run my Xamarin.Forms application using Visual Studio and I can't access any data from my Web API nor post any.
The Webservice class:
private readonly HttpClient _client;
public AccountService()
{
_client = new HttpClient
{
MaxResponseContentBufferSize = 256000
};
}
public async Task RegisterAsync(string email, string password, string confirmPassword)
{
var url = "http://169.254.80.80:61348/api/Account/Register";
var model = new RegisterBindingModel()
{
Email = email,
Password = password,
ConfirmPassword = confirmPassword
};
var json = JsonConvert.SerializeObject(model);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await _client.PostAsync(url, content);
}
The initiation of the registration
private async void Register()
{
try
{
using (UserDialogs.Instance.Loading())
{
await _accountServices.RegisterAsync
(Email, Password, ConfirmPassword);
}
UserDialogs.Instance.Alert("Register Successful");
await _navigation.PushAsync(new LoginPage());
}
catch
{
UserDialogs.Instance.Alert("Something wrong happened, Try again");
}
}
I've tried to access the localhost through Emulator using these IPs:
10.0.3.2
10.0.2.2
169.254.80.80
And I've tried my default gateways and my local IP address with and without ports, in regardless using postman i can work with my api flawlessly.
I don't get errors but the connection status code is not successful and I don't get any data and the newly registered account won't be posted to the api.
EDIT:
As for the answers I've changed my method to this:
public async Task<string> RegisterAsync(string email, string password, string confirmPassword)
{
var client = new HttpClient()
{
BaseAddress = new Uri("http://169.254.80.80:61348/")
};
var postData = new List<KeyValuePair<string, string>>();
var nvc = new List<KeyValuePair<string, string>>();
nvc.Add(new KeyValuePair<string, string>("email", email));
nvc.Add(new KeyValuePair<string, string>("password", password));
nvc.Add(new KeyValuePair<string, string>("confirmPassword", confirmPassword));
var req = new HttpRequestMessage(HttpMethod.Post, "api/Account/Register") { Content = new FormUrlEncodedContent(nvc) };
var res = await client.SendAsync(req);
if (res.IsSuccessStatusCode)
{
string result = await res.Content.ReadAsStringAsync();
string test = JsonConvert.DeserializeObject<string>(result);
return test;
}
return null;
}
and i call the web api using postman like this:
http://localhost:61348/api/Account/Register
I always prefer Newtonsoft Json.NET to carry out web request here is the code I have implemented in my case and it works great for me.
public static async Task<string> ResgisterUser(string email, string password, string confirmPassword)
{
var client = new HttpClient(new NativeMessageHandler());
client.BaseAddress = new Uri("http://192.168.101.119:8475/");
var postData = new List<KeyValuePair<string, string>>();
var nvc = new List<KeyValuePair<string, string>>();
nvc.Add(new KeyValuePair<string, string>("email", email));
nvc.Add(new KeyValuePair<string, string>("password", password));
nvc.Add(new KeyValuePair<string, string>("confirmPassword",confirmPassword));
var req = new HttpRequestMessage(HttpMethod.Post, "api/Vendor/Register") { Content = new FormUrlEncodedContent(nvc) };
var res = await client.SendAsync(req);
if (res.IsSuccessStatusCode)
{
string result = await res.Content.ReadAsStringAsync();
string test= JsonConvert.DeserializeObject<string>(result);
return test;
}
}
Hope it works for you.