-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow DBus data type='aay' #368
Closed
+608
−16
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ | |
pubspec.lock | ||
test/.test_cov.dart | ||
coverage/ | ||
/test/widget_test.dart | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,374 @@ | ||
import 'package:dbus/code_generator.dart'; | ||
import 'package:dbus/dbus.dart'; | ||
import 'package:dbus/src/dbus_bus_name.dart'; | ||
import 'package:dbus/src/dbus_error_name.dart'; | ||
import 'package:dbus/src/dbus_interface_name.dart'; | ||
import 'package:dbus/src/dbus_match_rule.dart'; | ||
import 'package:dbus/src/dbus_member_name.dart'; | ||
import 'package:dbus/src/dbus_message.dart'; | ||
import 'package:dbus/src/dbus_write_buffer.dart'; | ||
import 'package:dbus/src/dbus_uuid.dart'; | ||
import 'package:dbus/src/getuid.dart'; | ||
import 'package:dbus/src/dbus_value.dart'; | ||
|
||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
DBusClient systemDBusClient = DBusClient.system(); | ||
//These get filled in in | ||
late DBusRemoteObject serverObject; | ||
late DBusRemoteObject entryGroupObject; | ||
AvahiServiceConfig serviceConfig = AvahiServiceConfig('trixy',8765); | ||
|
||
void main() async { | ||
|
||
print('TEST Googles NearbyShare (Advertising) using Avahi via DBus on Linux.'); | ||
print(" *This requires DBus data type='aay' (array of array of bytes).\nSteps."); | ||
|
||
print('1. Attach to Avahi Server using the Dart DBus lib.'); | ||
print('2. Create an Avahi EntryGroup object.'); | ||
print('3. Add a NearbyShare Service definition to the new EntryGroup.'); | ||
print('4. Poll the EntryGroup status until the new service is ESTABLISHED'); | ||
print('5. Call Avahi ResolveService via DBus to print content of our'); | ||
print(' newly added NearbyShare (advertising) service.\n'); | ||
print('BEGIN TEST ON Platform.hostname: ${Platform.localHostname}'); | ||
|
||
await attachAvahiObjects(); | ||
|
||
await testAddAvahiService(); | ||
|
||
await testResolveAvahiService(); | ||
|
||
print('DONE\n'); | ||
print(''' | ||
If there were no errors, You should be able see the Nearby Share named | ||
${serviceConfig.fullAdvertisedName} | ||
from an android device or any Nearby Share client'''); | ||
print('\nPRESS ENTER TO QUIT (removes service)...'); | ||
|
||
var line = stdin.readLineSync(encoding: utf8); | ||
print('line: ${line}'); | ||
} | ||
|
||
/* SAMPLE AVAHI SERVICE FILE | ||
<service-group> | ||
<!-- Advertise ourselves using mDNS as a Google NearDrop Advertiser/Server | ||
(As Per https://github.com/grishka/NearDrop/blob/master/PROTOCOL.md) | ||
**Client side service name comes from TXT record and will show us as | ||
"roxypuke" on client side. | ||
**mDNS advertised name is special format as per PROTOCOL.md and shows up as | ||
"I1NISVT8n14AAA" | ||
$ avahi-browse -r _FC9F5ED42C8A._tcp | ||
--> | ||
<!-- mDNS advertised name of service | ||
Hex or Char Base64 | Base64URLSafe | ||
0x23, IW== | Iw | ||
4 random chars "SHIT", U0hJVA== | U0hJVA | ||
3 chars 0xFC, 0x9F, 0x5E, /J9e | _J9e | ||
2 0x00 chars AAA= | AAA | ||
Full Hex: 23 53 48 49 54 FC 9F 5E 00 00 | ||
Base64: I1NISVT8n14AAA== | ||
Base64url: I1NISVT8n14AAA | ||
--> | ||
<!--<name replace-wildcards="yes">Dog on %h</name>--> | ||
<name>I1NISVT8n14AAA</name> | ||
<service protocol="ipv4"> | ||
<domain-name></domain-name><!--yes empty domain-name is necessary...--> | ||
<type>_FC9F5ED42C8A._tcp</type> | ||
<port>8088</port> | ||
<!-- | ||
TXT record n="base64url encoded string" | ||
byte content: | ||
b1:000-version,0-visibility,011-laptop,0-reserved (00000110)=0x06 | ||
b2..b17 random hex 0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09 | ||
b18 (length of name of service as it will show up on the client nearby share screen "roxypuke") | ||
b19..b19+b18length user visible device name...roxypuke le 8 | ||
Hex content: | ||
0x06, | ||
0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09, | ||
0x08, | ||
0x72,0x6f,0x78,0x79,0x70,0x75,0x6b,0x65 | ||
Full Hex: 0x06,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x08,0x72,0x6f,0x78,0x79,0x70,0x75,0x6b,0x65 | ||
b64: BgYJBgkGCQYJBgkGCQYJBgkIcm94eXB1a2U= | ||
b64Url: BgYJBgkGCQYJBgkGCQYJBgkIcm94eXB1a2U | ||
--> | ||
<txt-record>n="BgYJBgkGCQYJBgkGCQYJBgkIcm94eXB1a2U"</txt-record> | ||
</service> | ||
</service-group> | ||
*/ | ||
|
||
// This class AvahiServiceConfig Config is a placeholder for props used to Advertise | ||
// our Nearby Share service using mDNS on Avahi daemon on local LAN. | ||
|
||
class AvahiServiceConfig { | ||
AvahiServiceConfig(this.nearbyAdvertisedName,this.port, | ||
{this.domain='local', | ||
this.host='', | ||
this.interface=-1, | ||
this.protocol=0, | ||
this.flags=0} | ||
); | ||
|
||
final String serviceType = '_FC9F5ED42C8A._tcp'; | ||
//The service Type is a fixed string. Check the PROTOCOL for why. | ||
final String serviceName = 'I1NISVT8n14AAA'; | ||
// The service Name is fixed here but we could allow the configuration of the | ||
// four random characters...its not really worth it so I just use "SHIT" | ||
// Hex or Char Base64 | Base64URLSafe | ||
// 0x23, IW== | Iw | ||
// 4 random chars "SHIT", U0hJVA== | U0hJVA | ||
// 3 chars 0xFC, 0x9F, 0x5E, /J9e | _J9e | ||
// 2 0x00 chars AAA= | AAA | ||
// Full Hex: 23 53 48 49 54 FC 9F 5E 00 00 | ||
// As Base64: I1NISVT8n14AAA== | ||
// As Base64url: I1NISVT8n14AAA | ||
|
||
int port; //Port number for nearby share server to listen on. | ||
String domain; //On a local linux lan this would be "local" | ||
String host; //fully qualified e.g. roxy.local | ||
int interface; //-1 all interfaces | ||
int protocol; //0 unspecified | ||
int flags; //0 unspecified | ||
|
||
String nearbyAdvertisedName; // see ctor. | ||
|
||
//If you pass a host name in, it needs to be fully qualified...e.g. myhost.local | ||
String get nearbyAdvertisedHost { | ||
if (this.host.trim().length == 0) { | ||
if (Platform.localHostname.contains('.')) return Platform.localHostname; | ||
else return Platform.localHostname+'.'+this.domain; | ||
} else return this.host.trim(); | ||
} | ||
|
||
String get fullAdvertisedName { | ||
String s = this.nearbyAdvertisedHost+':'+this.nearbyAdvertisedName; //TODO add HOST | ||
//String s = this.nearbyAdvertisedName; //Dont include host | ||
return s; | ||
} | ||
// Return base64url encoded string of byte(val=0x06) + random bytes + nearbyAdvertisedName | ||
// byte content: | ||
// b1:000-version,0-visibility,011-laptop,0-reserved (00000110)=0x06 | ||
// b2..b17 random hex 0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09 | ||
// b18 (length of name of service as it will show up on the client nearby share screen "roxypuke") | ||
// b19..(b19+b18) length = user visible device name...nearbyAdvertisedHost:nearbyAdvertisedName | ||
// Note that a TXT record is an array of arrays but for a NearbyShare service it is only | ||
// one string. | ||
// e.g. n="base64url encoded string based on byte(val=0x06) + random bytes + nearbyAdvertisedName" | ||
// There is no occassion (in this service definition) for actual array of array. | ||
// e.g. x=y,a=b | ||
// This method returns the string based on byte(val=0x06) + random bytes + nearbyAdvertisedName" | ||
|
||
String getSpecialEncodedFullAdvertisedName() { | ||
|
||
List<int> fan = utf8.encode(this.fullAdvertisedName); | ||
//cant be more than 256 bytes since length is single byte... | ||
List<int> byteArr = [6,6,9,6,9,6,9,6,9,6,9,6,9,6,9,6,9,fan.length]; | ||
byteArr.addAll(fan); | ||
// Should have something like this.... | ||
// 'BgYJBgkGCQYJBgkGCQYJBgkIcm94eXB1a2U==' | ||
return base64Url.encode(byteArr); | ||
} | ||
|
||
// TXT Record notes. 1st and ONLY byte array of the TXT record. | ||
//As per PROTOCOL.md from github NearDrop repo. | ||
//The TXT record of the mdns record contains the "Advertised Name" plus other | ||
//odd data as described above all globbed together and base64url'd. | ||
//We combine nearbyAdvertisedHost+':'+nearbyAdvertisedName as the | ||
// "Full Advertised Name" that a user connecting to us would see | ||
// e.g. "myhost.local:My Cool Nearby Share Name" | ||
// Should return something like n="BgYJBgkGCQYJBgkGCQYJBgkIcm94eXB1a2U==" | ||
String get txt { | ||
return('n="'+this.getSpecialEncodedFullAdvertisedName()+'"'); | ||
} | ||
|
||
@override String toString() { | ||
return | ||
'''AvahiServiceConfig( | ||
fullAdvertiseName: '${fullAdvertisedName}', | ||
port: ${port}, serviceName: '${serviceName}', serviceType: '${serviceType}', | ||
domain: '${domain}', host: '${nearbyAdvertisedHost}', | ||
interface: ${interface}, protocol: ${protocol}, flags: ${flags}, | ||
txt: '${this.txt}' | ||
) | ||
'''; | ||
} | ||
List<DBusValue> asAvahiAddServiceParamList() { | ||
List<int> txtAsBytes = utf8.encode(this.txt); | ||
List<DBusByte> txtAsByteList = []; | ||
txtAsBytes.forEach((bv) { | ||
txtAsByteList.add(DBusByte(bv)); | ||
}); | ||
DBusArray txtArr = DBusArray(DBusSignature('y'),txtAsByteList); | ||
|
||
var parmValues = [ | ||
DBusInt32(this.interface), //interface 3 | ||
DBusInt32(this.protocol), //protocol | ||
DBusUint32(this.flags), //flags 13 | ||
DBusString(this.serviceName), //name | ||
DBusString(this.serviceType), //type [DO NOT CHANGE] | ||
DBusString(this.domain), // domain | ||
DBusString(this.nearbyAdvertisedHost), // host (TODO add domain?) | ||
DBusUint16(this.port), //8019), //port | ||
DBusArray(DBusSignature('a'),[txtArr]), | ||
]; | ||
|
||
return parmValues; | ||
} | ||
|
||
List<DBusValue> asAvahiResolveServiceParamList() { | ||
var parmValues = [ | ||
DBusInt32(this.interface), //interface 3 | ||
DBusInt32(this.protocol), //protocol | ||
DBusString(this.serviceName), //name | ||
DBusString(this.serviceType), //type [DO NOT CHANGE] | ||
DBusString(this.domain), // domain | ||
DBusInt32(-1), //aprotocol? | ||
DBusUint32(this.flags), //flags | ||
]; | ||
return parmValues; | ||
} | ||
|
||
} | ||
|
||
|
||
Future<void> testResolveAvahiService() async { | ||
print(" --< testResolveAvahiService"); | ||
//Test ResolveService call | ||
//dbus-send --system --print-reply --type=method_call --dest=org.freedesktop.Avahi / | ||
// org.freedesktop.Avahi.Server.ResolveService int32:-1 int32:-1 | ||
// string:"I1NISVT8n14AAA" string:"_FC9F5ED42C8A._tcp" string:"" int32:-1 uint32:0 | ||
|
||
try { | ||
|
||
var res = await serverObjectInvoke('ResolveService',serviceConfig.asAvahiResolveServiceParamList()); | ||
print(' --< ResolveService results: ${res}'); | ||
|
||
} catch (ee) { | ||
print('--< RESOLVE SERVICE ERROR ${ee}'); | ||
} | ||
} | ||
|
||
//From avahi source interface org.freedesktop.Avahi.EntryGroup | ||
//<method name="AddService"> | ||
//<arg name="interface" type="i" direction="in"/> | ||
//<arg name="protocol" type="i" direction="in"/> | ||
//<arg name="flags" type="u" direction="in"/> | ||
//<arg name="name" type="s" direction="in"/> | ||
//<arg name="type" type="s" direction="in"/> | ||
//<arg name="domain" type="s" direction="in"/> | ||
//<arg name="host" type="s" direction="in"/> | ||
//<arg name="port" type="q" direction="in"/> | ||
//<arg name="txt" type="aay" direction="in"/> | ||
//</method> | ||
//Test adding a service to the Avahi daemon using DBus. | ||
//This assumes that attachAvahiObjects has already run. | ||
|
||
Future<void> testAddAvahiService() async { | ||
|
||
print(' --* Testing AddService to Entry Group ${entryGroupObject.path}'); | ||
print(' --* AVAHI SERVICE CONFIG: ${serviceConfig}'); | ||
print(' --* AVAHI ADD SERVICE PARMS: ${serviceConfig.asAvahiAddServiceParamList()}'); | ||
|
||
try { | ||
//assume that an EntryGroup was already added in attachAvahiObjects() | ||
|
||
var aRes = await entryGroupObjectInvoke('GetState',<DBusValue>[]); | ||
print(' --* GetState results: ${aRes}'); | ||
|
||
var bRes = await entryGroupObjectInvoke('AddService',serviceConfig.asAvahiAddServiceParamList()); | ||
print(' --* AddService results: ${bRes}'); | ||
|
||
var cRes = await entryGroupObjectInvoke('Commit',<DBusValue>[]); | ||
print(' --* Commit results: ${cRes}'); | ||
|
||
var dRes = await entryGroupObjectInvoke('GetState',<DBusValue>[]); | ||
print(' --* GetState results: ${dRes}'); | ||
|
||
var eRes = await entryGroupObjectInvoke('IsEmpty',<DBusValue>[]); | ||
print(' --* IsEmpty results: ${eRes}'); | ||
|
||
//typedef enum { | ||
// AVAHI_ENTRY_GROUP_UNCOMMITED, /**< The group has not yet been committed, the user must still call avahi_entry_group_commit() */ | ||
// AVAHI_ENTRY_GROUP_REGISTERING, /**< The entries of the group are currently being registered */ | ||
// AVAHI_ENTRY_GROUP_ESTABLISHED, /**< The entries have successfully been established */ | ||
// AVAHI_ENTRY_GROUP_COLLISION, /**< A name collision for one of the entries in the group has been detected, the entries have been withdrawn */ | ||
// AVAHI_ENTRY_GROUP_FAILURE /**< Some kind of failure happened, the entries have been withdrawn */ | ||
//} AvahiEntryGroupState; | ||
int curState = (dRes[0] as DBusInt32).value; | ||
while (curState<2) { | ||
print(' --* LOOP curState: ${curState}'); | ||
var lRes = await entryGroupObjectInvoke('GetState',<DBusValue>[]); | ||
curState = (lRes[0] as DBusInt32).value; | ||
await Future.delayed(Duration(seconds: 2)); | ||
} | ||
print(' --* LOOP FINISHED STATE: ${curState}'); | ||
print(' --* SERVICE ESTABLISHED'); | ||
} catch (ee) { | ||
print('--* ADD SERVICE ERROR ${ee}'); | ||
} | ||
} | ||
|
||
|
||
Future<void> attachAvahiObjects() async { | ||
try { | ||
print('--> Attaching Avahi Server and EntryGroup objects'); | ||
serverObject = DBusRemoteObject(systemDBusClient, | ||
name: 'org.freedesktop.Avahi', | ||
path: DBusObjectPath('/') | ||
); | ||
|
||
//EntryGroupNew call | ||
//dbus-send --system --print-reply --type=method_call --dest=org.freedesktop.Avahi / | ||
// org.freedesktop.Avahi.Server.EntryGroupNew | ||
|
||
var nbs_results = await serverObjectInvoke('EntryGroupNew',<DBusValue>[]); | ||
print(' -->EntryGroupNew results: ${nbs_results}'); | ||
|
||
DBusObjectPath entryGroupPath = nbs_results[0] as DBusObjectPath; | ||
print(' -->New EntryGroupPath: ${entryGroupPath}'); | ||
|
||
entryGroupObject = DBusRemoteObject(systemDBusClient, | ||
name: 'org.freedesktop.Avahi', | ||
path: entryGroupPath | ||
); | ||
|
||
var eg_results = await entryGroupObjectInvoke('GetState',<DBusValue>[]); | ||
int egState = (eg_results[0] as DBusInt32).value; | ||
print(' -->GetState result: ${egState}'); | ||
|
||
print('-->Avahi objects attached.'); | ||
} catch (ae) { | ||
print('-->ATTACH ERROR: ${ae}'); | ||
} | ||
} | ||
|
||
// UTILITY FUNCTIONS BELOW | ||
|
||
Future<List<DBusValue>> serverObjectInvoke(methodName,args) async { | ||
final interfaceName = 'org.freedesktop.Avahi.Server'; | ||
var result = await serverObject.callMethod( | ||
interfaceName, methodName, args | ||
); | ||
return result.returnValues; | ||
} | ||
Future<List<DBusValue>> entryGroupObjectInvoke(methodName,args) async { | ||
final interfaceName = 'org.freedesktop.Avahi.EntryGroup'; | ||
var eg_result = await entryGroupObject.callMethod( | ||
interfaceName, methodName, args | ||
); | ||
//print('RAW RESULT ${eg_result}'); | ||
return eg_result.returnValues; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import 'package:dbus/code_generator.dart'; | ||
import 'package:dbus/dbus.dart'; | ||
import 'package:dbus/src/dbus_bus_name.dart'; | ||
import 'package:dbus/src/dbus_error_name.dart'; | ||
import 'package:dbus/src/dbus_interface_name.dart'; | ||
import 'package:dbus/src/dbus_match_rule.dart'; | ||
import 'package:dbus/src/dbus_member_name.dart'; | ||
import 'package:dbus/src/dbus_message.dart'; | ||
import 'package:dbus/src/dbus_write_buffer.dart'; | ||
import 'package:dbus/src/dbus_uuid.dart'; | ||
import 'package:dbus/src/getuid.dart'; | ||
import 'package:dbus/src/dbus_value.dart'; | ||
|
||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
|
||
void main() async { | ||
print('TEST new array of arrays DBus types'); | ||
|
||
//type=iaayi | ||
var test_aay = [ | ||
DBusInt32(42), | ||
DBusArray(DBusSignature('a'), [ | ||
DBusArray(DBusSignature('y'), [DBusByte(88), DBusByte(88), DBusByte(88)]) | ||
]), | ||
DBusInt32(69), | ||
]; | ||
print('TEST Signature [iaayi]'); | ||
dumpAsMessage(test_aay); | ||
|
||
//type = iaasi | ||
var test_aas = [ | ||
DBusInt32(42), | ||
DBusArray(DBusSignature('a'), [ | ||
DBusArray(DBusSignature('s'), | ||
[DBusString('XXX'), DBusString('YYY'), DBusString('ZZZ')]) | ||
]), | ||
DBusInt32(69), | ||
]; | ||
print('TEST Signature [iaasi]'); | ||
dumpAsMessage(test_aas); | ||
|
||
//type = iaayaasi | ||
var test_both = [ | ||
DBusInt32(42), | ||
DBusArray(DBusSignature('a'), [ | ||
DBusArray(DBusSignature('y'), [DBusByte(88), DBusByte(88), DBusByte(88)]), | ||
]), | ||
DBusArray(DBusSignature('a'), [ | ||
DBusArray(DBusSignature('s'), | ||
[DBusString('XXX'), DBusString('YYY'), DBusString('ZZZ')]) | ||
]), | ||
DBusInt32(69), | ||
]; | ||
print('TEST Signature [iaayaasi]'); | ||
dumpAsMessage(test_both); | ||
|
||
// type=iasi | ||
var test_str_only = [ | ||
DBusInt32(42), | ||
DBusString('XXX'), | ||
DBusInt32(69), | ||
]; | ||
print('TEST Signature [isi]'); | ||
dumpAsMessage(test_str_only); | ||
|
||
// type=ias | ||
var test_str_no_trailing = [ | ||
DBusInt32(42), | ||
DBusString('XXX'), | ||
]; | ||
print('TEST Signature [is]'); | ||
dumpAsMessage(test_str_no_trailing); | ||
|
||
|
||
var test_fail = [ | ||
DBusInt32(42), | ||
DBusArray(DBusSignature('a'), [ | ||
DBusArray(DBusSignature('y'), [DBusByte(88), DBusByte(88), DBusByte(88)]), | ||
DBusArray(DBusSignature('y'), [DBusByte(99), DBusByte(99), DBusByte(99)]), | ||
]), | ||
]; | ||
print('TEST Signature [iaay]'); | ||
dumpAsMessage(test_fail); | ||
|
||
print('DONE\n'); | ||
} | ||
|
||
void dumpAsMessage(List<DBusValue> valArr) { | ||
print('++++Test fake message with values\n'); | ||
DBusMessage fakeMsg = DBusMessage( | ||
DBusMessageType.methodCall, | ||
path: null, | ||
interface:null, | ||
member:null, | ||
errorName:null, | ||
replySerial:null, | ||
destination: null, | ||
sender: null, | ||
values: valArr, | ||
); | ||
|
||
DBusWriteBuffer dbwb = DBusWriteBuffer(); | ||
dbwb.writeMessage(fakeMsg); | ||
|
||
print(' ++++Fake message with values\n'+fakeMsg.toString()); | ||
print(' ++++RAW fake message bytes\n${dbwb.data}'); | ||
//dbwb.data.forEach((b)=> print(b.runtimeType.toString()+' => '+b.toString())); | ||
print('++++DONE Test fake message with values'); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't seem to be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was me trying to learn AndroidStudio (click this, click that, suddenly files show up) to run the tests.