4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped
5 |
6 | interface MochaSetupOptions {
7 | //milliseconds to wait before considering a test slow
8 | slow?: number;
9 |
10 | // timeout in milliseconds
11 | timeout?: number;
12 |
13 | // ui name "bdd", "tdd", "exports" etc
14 | ui?: string;
15 |
16 | //array of accepted globals
17 | globals?: any[];
18 |
19 | // reporter instance (function or string), defaults to `mocha.reporters.Spec`
20 | reporter?: any;
21 |
22 | // bail on the first test failure
23 | bail?: boolean;
24 |
25 | // ignore global leaks
26 | ignoreLeaks?: boolean;
27 |
28 | // grep string or regexp to filter tests with
29 | grep?: any;
30 | }
31 |
32 | interface MochaDone {
33 | (error?: Error): void;
34 | }
35 |
36 | declare var mocha: Mocha;
37 | declare var describe: Mocha.IContextDefinition;
38 | declare var xdescribe: Mocha.IContextDefinition;
39 | // alias for `describe`
40 | declare var context: Mocha.IContextDefinition;
41 | // alias for `describe`
42 | declare var suite: Mocha.IContextDefinition;
43 | declare var it: Mocha.ITestDefinition;
44 | declare var xit: Mocha.ITestDefinition;
45 | // alias for `it`
46 | declare var test: Mocha.ITestDefinition;
47 |
48 | declare function before(action: () => void): void;
49 |
50 | declare function before(action: (done: MochaDone) => void): void;
51 |
52 | declare function before(description: string, action: () => void): void;
53 |
54 | declare function before(description: string, action: (done: MochaDone) => void): void;
55 |
56 | declare function setup(action: () => void): void;
57 |
58 | declare function setup(action: (done: MochaDone) => void): void;
59 |
60 | declare function after(action: () => void): void;
61 |
62 | declare function after(action: (done: MochaDone) => void): void;
63 |
64 | declare function after(description: string, action: () => void): void;
65 |
66 | declare function after(description: string, action: (done: MochaDone) => void): void;
67 |
68 | declare function teardown(action: () => void): void;
69 |
70 | declare function teardown(action: (done: MochaDone) => void): void;
71 |
72 | declare function beforeEach(action: () => void): void;
73 |
74 | declare function beforeEach(action: (done: MochaDone) => void): void;
75 |
76 | declare function beforeEach(description: string, action: () => void): void;
77 |
78 | declare function beforeEach(description: string, action: (done: MochaDone) => void): void;
79 |
80 | declare function suiteSetup(action: () => void): void;
81 |
82 | declare function suiteSetup(action: (done: MochaDone) => void): void;
83 |
84 | declare function afterEach(action: () => void): void;
85 |
86 | declare function afterEach(action: (done: MochaDone) => void): void;
87 |
88 | declare function afterEach(description: string, action: () => void): void;
89 |
90 | declare function afterEach(description: string, action: (done: MochaDone) => void): void;
91 |
92 | declare function suiteTeardown(action: () => void): void;
93 |
94 | declare function suiteTeardown(action: (done: MochaDone) => void): void;
95 |
96 | declare class Mocha {
97 | constructor(options?: {
98 | grep?: RegExp;
99 | ui?: string;
100 | reporter?: string;
101 | timeout?: number;
102 | bail?: boolean;
103 | });
104 |
105 | /** Setup mocha with the given options. */
106 | setup(options: MochaSetupOptions): Mocha;
107 | bail(value?: boolean): Mocha;
108 | addFile(file: string): Mocha;
109 | /** Sets reporter by name, defaults to "spec". */
110 | reporter(name: string): Mocha;
111 | /** Sets reporter constructor, defaults to mocha.reporters.Spec. */
112 | reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha;
113 | ui(value: string): Mocha;
114 | grep(value: string): Mocha;
115 | grep(value: RegExp): Mocha;
116 | invert(): Mocha;
117 | ignoreLeaks(value: boolean): Mocha;
118 | checkLeaks(): Mocha;
119 | /**
120 | * Function to allow assertion libraries to throw errors directly into mocha.
121 | * This is useful when running tests in a browser because window.onerror will
122 | * only receive the 'message' attribute of the Error.
123 | */
124 | throwError(error: Error): void;
125 | /** Enables growl support. */
126 | growl(): Mocha;
127 | globals(value: string): Mocha;
128 | globals(values: string[]): Mocha;
129 | useColors(value: boolean): Mocha;
130 | useInlineDiffs(value: boolean): Mocha;
131 | timeout(value: number): Mocha;
132 | slow(value: number): Mocha;
133 | enableTimeouts(value: boolean): Mocha;
134 | asyncOnly(value: boolean): Mocha;
135 | noHighlighting(value: boolean): Mocha;
136 | /** Runs tests and invokes `onComplete()` when finished. */
137 | run(onComplete?: (failures: number) => void): Mocha.IRunner;
138 | }
139 |
140 | // merge the Mocha class declaration with a module
141 | declare module Mocha {
142 | /** Partial interface for Mocha's `Runnable` class. */
143 | interface IRunnable {
144 | title: string;
145 | fn: Function;
146 | async: boolean;
147 | sync: boolean;
148 | timedOut: boolean;
149 | }
150 |
151 | /** Partial interface for Mocha's `Suite` class. */
152 | interface ISuite {
153 | parent: ISuite;
154 | title: string;
155 |
156 | fullTitle(): string;
157 | }
158 |
159 | /** Partial interface for Mocha's `Test` class. */
160 | interface ITest extends IRunnable {
161 | parent: ISuite;
162 | pending: boolean;
163 |
164 | fullTitle(): string;
165 | }
166 |
167 | /** Partial interface for Mocha's `Runner` class. */
168 | interface IRunner {}
169 |
170 | interface IContextDefinition {
171 | (description: string, spec: () => void): ISuite;
172 | only(description: string, spec: () => void): ISuite;
173 | skip(description: string, spec: () => void): void;
174 | timeout(ms: number): void;
175 | }
176 |
177 | interface ITestDefinition {
178 | (expectation: string, assertion?: () => void): ITest;
179 | (expectation: string, assertion?: (done: MochaDone) => void): ITest;
180 | only(expectation: string, assertion?: () => void): ITest;
181 | only(expectation: string, assertion?: (done: MochaDone) => void): ITest;
182 | skip(expectation: string, assertion?: () => void): void;
183 | skip(expectation: string, assertion?: (done: MochaDone) => void): void;
184 | timeout(ms: number): void;
185 | }
186 |
187 | export module reporters {
188 | export class Base {
189 | stats: {
190 | suites: number;
191 | tests: number;
192 | passes: number;
193 | pending: number;
194 | failures: number;
195 | };
196 |
197 | constructor(runner: IRunner);
198 | }
199 |
200 | export class Doc extends Base {}
201 | export class Dot extends Base {}
202 | export class HTML extends Base {}
203 | export class HTMLCov extends Base {}
204 | export class JSON extends Base {}
205 | export class JSONCov extends Base {}
206 | export class JSONStream extends Base {}
207 | export class Landing extends Base {}
208 | export class List extends Base {}
209 | export class Markdown extends Base {}
210 | export class Min extends Base {}
211 | export class Nyan extends Base {}
212 | export class Progress extends Base {
213 | /**
214 | * @param options.open String used to indicate the start of the progress bar.
215 | * @param options.complete String used to indicate a complete test on the progress bar.
216 | * @param options.incomplete String used to indicate an incomplete test on the progress bar.
217 | * @param options.close String used to indicate the end of the progress bar.
218 | */
219 | constructor(runner: IRunner, options?: {
220 | open?: string;
221 | complete?: string;
222 | incomplete?: string;
223 | close?: string;
224 | });
225 | }
226 | export class Spec extends Base {}
227 | export class TAP extends Base {}
228 | export class XUnit extends Base {
229 | constructor(runner: IRunner, options?: any);
230 | }
231 | }
232 | }
233 |
234 | declare module "mocha" {
235 | export = Mocha;
236 | }
237 |
--------------------------------------------------------------------------------
/demo.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Web Bluetooth / Battery Level Sample
13 |
14 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Web Bluetooth / Battery Level Sample
48 |
49 | Available in Chrome 45+ |
50 | View Source |
51 | View on GitHub |
52 | Browse Samples
53 |
54 | The Web Bluetooth
55 | API discovers and communicates with devices over the Bluetooth 4 wireless
56 | standard using the Generic Attribute Profile (GATT). It is currently only
57 | partially implemented in Chrome OS and Android M behind the experimental flag
58 | chrome://flags/#enable-web-bluetooth. Check out all Web Bluetooth Samples .
60 |
61 |
62 | This sample illustrates the use of the Web Bluetooth API to retrieve battery
63 | information from a nearby Bluetooth Device advertising Battery information with
64 | Bluetooth Low Energy. You may want to try this demo with the BLE Peripheral
65 | Simulator App from the Google
67 | Play Store .
68 |
69 | Get Bluetooth Device's Battery Level
70 |
71 |
98 |
99 | Live Output
100 |
105 |
106 |
107 |
108 |
109 |
110 |
118 |
119 |
120 |
121 |
122 | JavaScript Snippet
123 |
124 |
125 |
126 | function onButtonClick () {
127 | 'use strict' ;
128 |
129 | log ( 'Requesting Bluetooth Device...' );
130 | navigator . bluetooth . requestDevice (
131 | { filters : [{ services : [ 'battery_service' ]}]})
132 | . then ( device => {
133 | log ( '> Found ' + device . name );
134 | log ( 'Connecting to GATT Server...' );
135 | return device . connectGATT ();
136 | })
137 | . then ( server => {
138 | log ( 'Getting Battery Service...' );
139 | return server . getPrimaryService ( 'battery_service' );
140 | })
141 | . then ( service => {
142 | log ( 'Getting Battery Level Characteristic...' );
143 | return service . getCharacteristic ( 'battery_level' );
144 | })
145 | . then ( characteristic => {
146 | log ( 'Reading Battery Level...' );
147 | return characteristic . readValue ();
148 | })
149 | . then ( buffer => {
150 | let data = new DataView ( buffer );
151 | let batteryLevel = data . getUint8 ( 0 );
152 | log ( '> Battery Level is ' + batteryLevel + '%' );
153 | })
154 | . catch ( error => {
155 | log ( 'Argh! ' + error );
156 | });
157 | }
158 |
159 |
160 |
161 |
162 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/btscale.min.js:
--------------------------------------------------------------------------------
1 | !function t(e,n,r){function i(c,s){if(!n[c]){if(!e[c]){var a="function"==typeof require&&require;if(!s&&a)return a(c,!0);if(o)return o(c,!0);var u=new Error("Cannot find module '"+c+"'");throw u.code="MODULE_NOT_FOUND",u}var h=n[c]={exports:{}};e[c][0].call(h.exports,function(t){var n=e[c][1][t];return i(n?n:t)},h,h.exports,t,e,n,r)}return n[c].exports}for(var o="function"==typeof require&&require,c=0;c=0&&(1===n.length?delete this.listeners_[t]:n.splice(r,1))}},t.prototype.dispatchEvent=function(t){if(!this.listeners_)return!0;var e=this;t.__defineGetter__("target",function(){return e});var n=t.type,r=0;if(n in this.listeners_)for(var i=this.listeners_[n].concat(),o=0,c=void 0;c=i[o];o++)r|=c.handleEvent?c.handleEvent.call(c,t)===!1:c.call(this,t)===!1;return!r&&!t.defaultPrevented},t}();n.BTSEventTarget=r},{}],3:[function(t,e,n){"use strict";function r(){var t=E++;return E&=255,t}function i(t){E=255&t}function o(t,e,n){for(var r=0;rw)throw"payload too long: "+n.length;var i=new ArrayBuffer(8+n.length),c=new Uint8Array(i),a=r();c[0]=y.MAGIC1,c[1]=y.MAGIC2,c[2]=5+n.length,c[3]=t,c[4]=a,c[5]=e,c[6]=255&n.length;var u=new Uint8Array(i,7,n.length);o(u,n,a);var h=new Uint8Array(i,3,n.length+4);return c[7+n.length]=s(h),i}function u(t){var e=t.byteLength;if(e){var n=new Uint8Array(t);if(8>e)throw"data too short: "+e;if(n[0]!==y.MAGIC1&&n[1]!==y.MAGIC2)throw"don't have the magic";var r=n[2],i=new Uint8Array(t.slice(3,e-1)),o=s(i);if(n[e-1]!==o)throw"checksum mismatch "+n[e-1]+" !== "+o;var a=n[3],u=n[4],h=n[5],l=n[6];if(r!==e-3)throw"length mismatch 1 "+r+" !== "+(e-3);if(l!==e-8)throw"length mismatch 2";var d=new Uint8Array(t.slice(7,e-1)),f=c(d,u);return new C(a,h,f)}}function h(t,e,n){void 0===t&&(t=1),void 0===e&&(e=100),void 0===n&&(n=1);var r=[255&t,255&e,255&n];return a(4,0,r)}function l(){var t=[0,0];return a(12,0,t)}function d(){var t=[5];return a(12,0,t)}function f(){var t=[6];return a(12,0,t)}function v(){var t=[7];return a(12,0,t)}function p(t){void 0===t&&(t=20);var e=[8,255&t];return a(12,0,e)}function g(){return a(2,0,[])}var y=t("./constants"),w=10,E=0;n.setSequenceId=i;var C=function(){function t(t,e,n){if(this.type=t,this.id=e,this.payload=n,this.value=null,5===t){for(var r=((255&n[1])<<8)+(255&n[0]),i=0;i ,
4 | // Bart van der Schoor ,
5 | // Andrew Brown ,
6 | // Olivier Chevet
7 | // Definitions: https://github.com/borisyankov/DefinitelyTyped
8 |
9 | //
10 |
11 | declare module Chai {
12 |
13 | interface ChaiStatic {
14 | expect: ExpectStatic;
15 | should(): Should;
16 | /**
17 | * Provides a way to extend the internals of Chai
18 | */
19 | use(fn: (chai: any, utils: any) => void): any;
20 | assert: AssertStatic;
21 | config: Config;
22 | AssertionError: AssertionError;
23 | }
24 |
25 | export interface ExpectStatic extends AssertionStatic {
26 | fail(actual?: any, expected?: any, message?: string, operator?: string): void;
27 | }
28 |
29 | export interface AssertStatic extends Assert {
30 | }
31 |
32 | export interface AssertionStatic {
33 | (target: any, message?: string): Assertion;
34 | }
35 |
36 | interface ShouldAssertion {
37 | equal(value1: any, value2: any, message?: string): void;
38 | Throw: ShouldThrow;
39 | throw: ShouldThrow;
40 | exist(value: any, message?: string): void;
41 | }
42 |
43 | interface Should extends ShouldAssertion {
44 | not: ShouldAssertion;
45 | fail(actual: any, expected: any, message?: string, operator?: string): void;
46 | }
47 |
48 | interface ShouldThrow {
49 | (actual: Function): void;
50 | (actual: Function, expected: string|RegExp, message?: string): void;
51 | (actual: Function, constructor: Error|Function, expected?: string|RegExp, message?: string): void;
52 | }
53 |
54 | interface Assertion extends LanguageChains, NumericComparison, TypeComparison {
55 | not: Assertion;
56 | deep: Deep;
57 | any: KeyFilter;
58 | all: KeyFilter;
59 | a: TypeComparison;
60 | an: TypeComparison;
61 | include: Include;
62 | includes: Include;
63 | contain: Include;
64 | contains: Include;
65 | ok: Assertion;
66 | true: Assertion;
67 | false: Assertion;
68 | null: Assertion;
69 | undefined: Assertion;
70 | NaN: Assertion;
71 | exist: Assertion;
72 | empty: Assertion;
73 | arguments: Assertion;
74 | Arguments: Assertion;
75 | equal: Equal;
76 | equals: Equal;
77 | eq: Equal;
78 | eql: Equal;
79 | eqls: Equal;
80 | property: Property;
81 | ownProperty: OwnProperty;
82 | haveOwnProperty: OwnProperty;
83 | ownPropertyDescriptor: OwnPropertyDescriptor;
84 | haveOwnPropertyDescriptor: OwnPropertyDescriptor;
85 | length: Length;
86 | lengthOf: Length;
87 | match: Match;
88 | matches: Match;
89 | string(string: string, message?: string): Assertion;
90 | keys: Keys;
91 | key(string: string): Assertion;
92 | throw: Throw;
93 | throws: Throw;
94 | Throw: Throw;
95 | respondTo: RespondTo;
96 | respondsTo: RespondTo;
97 | itself: Assertion;
98 | satisfy: Satisfy;
99 | satisfies: Satisfy;
100 | closeTo(expected: number, delta: number, message?: string): Assertion;
101 | members: Members;
102 | increase: PropertyChange;
103 | increases: PropertyChange;
104 | decrease: PropertyChange;
105 | decreases: PropertyChange;
106 | change: PropertyChange;
107 | changes: PropertyChange;
108 | extensible: Assertion;
109 | sealed: Assertion;
110 | frozen: Assertion;
111 |
112 | }
113 |
114 | interface LanguageChains {
115 | to: Assertion;
116 | be: Assertion;
117 | been: Assertion;
118 | is: Assertion;
119 | that: Assertion;
120 | which: Assertion;
121 | and: Assertion;
122 | has: Assertion;
123 | have: Assertion;
124 | with: Assertion;
125 | at: Assertion;
126 | of: Assertion;
127 | same: Assertion;
128 | }
129 |
130 | interface NumericComparison {
131 | above: NumberComparer;
132 | gt: NumberComparer;
133 | greaterThan: NumberComparer;
134 | least: NumberComparer;
135 | gte: NumberComparer;
136 | below: NumberComparer;
137 | lt: NumberComparer;
138 | lessThan: NumberComparer;
139 | most: NumberComparer;
140 | lte: NumberComparer;
141 | within(start: number, finish: number, message?: string): Assertion;
142 | }
143 |
144 | interface NumberComparer {
145 | (value: number, message?: string): Assertion;
146 | }
147 |
148 | interface TypeComparison {
149 | (type: string, message?: string): Assertion;
150 | instanceof: InstanceOf;
151 | instanceOf: InstanceOf;
152 | }
153 |
154 | interface InstanceOf {
155 | (constructor: Object, message?: string): Assertion;
156 | }
157 |
158 | interface Deep {
159 | equal: Equal;
160 | include: Include;
161 | property: Property;
162 | members: Members;
163 | }
164 |
165 | interface KeyFilter {
166 | keys: Keys;
167 | }
168 |
169 | interface Equal {
170 | (value: any, message?: string): Assertion;
171 | }
172 |
173 | interface Property {
174 | (name: string, value?: any, message?: string): Assertion;
175 | }
176 |
177 | interface OwnProperty {
178 | (name: string, message?: string): Assertion;
179 | }
180 |
181 | interface OwnPropertyDescriptor {
182 | (name: string, descriptor: PropertyDescriptor, message?: string): Assertion;
183 | (name: string, message?: string): Assertion;
184 | }
185 |
186 | interface Length extends LanguageChains, NumericComparison {
187 | (length: number, message?: string): Assertion;
188 | }
189 |
190 | interface Include {
191 | (value: Object, message?: string): Assertion;
192 | (value: string, message?: string): Assertion;
193 | (value: number, message?: string): Assertion;
194 | keys: Keys;
195 | members: Members;
196 | any: KeyFilter;
197 | all: KeyFilter;
198 | }
199 |
200 | interface Match {
201 | (regexp: RegExp|string, message?: string): Assertion;
202 | }
203 |
204 | interface Keys {
205 | (...keys: string[]): Assertion;
206 | (keys: any[]): Assertion;
207 | (keys: Object): Assertion;
208 | }
209 |
210 | interface Throw {
211 | (): Assertion;
212 | (expected: string, message?: string): Assertion;
213 | (expected: RegExp, message?: string): Assertion;
214 | (constructor: Error, expected?: string, message?: string): Assertion;
215 | (constructor: Error, expected?: RegExp, message?: string): Assertion;
216 | (constructor: Function, expected?: string, message?: string): Assertion;
217 | (constructor: Function, expected?: RegExp, message?: string): Assertion;
218 | }
219 |
220 | interface RespondTo {
221 | (method: string, message?: string): Assertion;
222 | }
223 |
224 | interface Satisfy {
225 | (matcher: Function, message?: string): Assertion;
226 | }
227 |
228 | interface Members {
229 | (set: any[], message?: string): Assertion;
230 | }
231 |
232 | interface PropertyChange {
233 | (object: Object, prop: string, msg?: string): Assertion;
234 | }
235 |
236 | export interface Assert {
237 | /**
238 | * @param expression Expression to test for truthiness.
239 | * @param message Message to display on error.
240 | */
241 | (expression: any, message?: string): void;
242 |
243 | fail(actual?: any, expected?: any, msg?: string, operator?: string): void;
244 |
245 | ok(val: any, msg?: string): void;
246 | isOk(val: any, msg?: string): void;
247 | notOk(val: any, msg?: string): void;
248 | isNotOk(val: any, msg?: string): void;
249 |
250 | equal(act: any, exp: any, msg?: string): void;
251 | notEqual(act: any, exp: any, msg?: string): void;
252 |
253 | strictEqual(act: any, exp: any, msg?: string): void;
254 | notStrictEqual(act: any, exp: any, msg?: string): void;
255 |
256 | deepEqual(act: any, exp: any, msg?: string): void;
257 | notDeepEqual(act: any, exp: any, msg?: string): void;
258 |
259 | isTrue(val: any, msg?: string): void;
260 | isFalse(val: any, msg?: string): void;
261 |
262 | isNull(val: any, msg?: string): void;
263 | isNotNull(val: any, msg?: string): void;
264 |
265 | isUndefined(val: any, msg?: string): void;
266 | isDefined(val: any, msg?: string): void;
267 |
268 | isNaN(val: any, msg?: string): void;
269 | isNotNaN(val: any, msg?: string): void;
270 |
271 | isAbove(val: number, abv: number, msg?: string): void;
272 | isBelow(val: number, blw: number, msg?: string): void;
273 |
274 | isFunction(val: any, msg?: string): void;
275 | isNotFunction(val: any, msg?: string): void;
276 |
277 | isObject(val: any, msg?: string): void;
278 | isNotObject(val: any, msg?: string): void;
279 |
280 | isArray(val: any, msg?: string): void;
281 | isNotArray(val: any, msg?: string): void;
282 |
283 | isString(val: any, msg?: string): void;
284 | isNotString(val: any, msg?: string): void;
285 |
286 | isNumber(val: any, msg?: string): void;
287 | isNotNumber(val: any, msg?: string): void;
288 |
289 | isBoolean(val: any, msg?: string): void;
290 | isNotBoolean(val: any, msg?: string): void;
291 |
292 | typeOf(val: any, type: string, msg?: string): void;
293 | notTypeOf(val: any, type: string, msg?: string): void;
294 |
295 | instanceOf(val: any, type: Function, msg?: string): void;
296 | notInstanceOf(val: any, type: Function, msg?: string): void;
297 |
298 | include(exp: string, inc: any, msg?: string): void;
299 | include(exp: any[], inc: any, msg?: string): void;
300 |
301 | notInclude(exp: string, inc: any, msg?: string): void;
302 | notInclude(exp: any[], inc: any, msg?: string): void;
303 |
304 | match(exp: any, re: RegExp, msg?: string): void;
305 | notMatch(exp: any, re: RegExp, msg?: string): void;
306 |
307 | property(obj: Object, prop: string, msg?: string): void;
308 | notProperty(obj: Object, prop: string, msg?: string): void;
309 | deepProperty(obj: Object, prop: string, msg?: string): void;
310 | notDeepProperty(obj: Object, prop: string, msg?: string): void;
311 |
312 | propertyVal(obj: Object, prop: string, val: any, msg?: string): void;
313 | propertyNotVal(obj: Object, prop: string, val: any, msg?: string): void;
314 |
315 | deepPropertyVal(obj: Object, prop: string, val: any, msg?: string): void;
316 | deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string): void;
317 |
318 | lengthOf(exp: any, len: number, msg?: string): void;
319 | //alias frenzy
320 | throw(fn: Function, msg?: string): void;
321 | throw(fn: Function, regExp: RegExp): void;
322 | throw(fn: Function, errType: Function, msg?: string): void;
323 | throw(fn: Function, errType: Function, regExp: RegExp): void;
324 |
325 | throws(fn: Function, msg?: string): void;
326 | throws(fn: Function, regExp: RegExp): void;
327 | throws(fn: Function, errType: Function, msg?: string): void;
328 | throws(fn: Function, errType: Function, regExp: RegExp): void;
329 |
330 | Throw(fn: Function, msg?: string): void;
331 | Throw(fn: Function, regExp: RegExp): void;
332 | Throw(fn: Function, errType: Function, msg?: string): void;
333 | Throw(fn: Function, errType: Function, regExp: RegExp): void;
334 |
335 | doesNotThrow(fn: Function, msg?: string): void;
336 | doesNotThrow(fn: Function, regExp: RegExp): void;
337 | doesNotThrow(fn: Function, errType: Function, msg?: string): void;
338 | doesNotThrow(fn: Function, errType: Function, regExp: RegExp): void;
339 |
340 | operator(val: any, operator: string, val2: any, msg?: string): void;
341 | closeTo(act: number, exp: number, delta: number, msg?: string): void;
342 |
343 | sameMembers(set1: any[], set2: any[], msg?: string): void;
344 | sameDeepMembers(set1: any[], set2: any[], msg?: string): void;
345 | includeMembers(superset: any[], subset: any[], msg?: string): void;
346 |
347 | ifError(val: any, msg?: string): void;
348 |
349 | isExtensible(obj: {}, msg?: string): void;
350 | extensible(obj: {}, msg?: string): void;
351 | isNotExtensible(obj: {}, msg?: string): void;
352 | notExtensible(obj: {}, msg?: string): void;
353 |
354 | isSealed(obj: {}, msg?: string): void;
355 | sealed(obj: {}, msg?: string): void;
356 | isNotSealed(obj: {}, msg?: string): void;
357 | notSealed(obj: {}, msg?: string): void;
358 |
359 | isFrozen(obj: Object, msg?: string): void;
360 | frozen(obj: Object, msg?: string): void;
361 | isNotFrozen(obj: Object, msg?: string): void;
362 | notFrozen(obj: Object, msg?: string): void;
363 |
364 |
365 | }
366 |
367 | export interface Config {
368 | includeStack: boolean;
369 | }
370 |
371 | export class AssertionError {
372 | constructor(message: string, _props?: any, ssf?: Function);
373 | name: string;
374 | message: string;
375 | showDiff: boolean;
376 | stack: string;
377 | }
378 | }
379 |
380 | declare var chai: Chai.ChaiStatic;
381 |
382 | declare module "chai" {
383 | export = chai;
384 | }
385 |
386 | interface Object {
387 | should: Chai.Assertion;
388 | }
389 |
--------------------------------------------------------------------------------
/src/vendor/almond.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
3 | * Available via the MIT or new BSD license.
4 | * see: http://github.com/jrburke/almond for details
5 | */
6 | //Going sloppy to avoid 'use strict' string cost, but strict practices should
7 | //be followed.
8 | /*jslint sloppy: true */
9 | /*global setTimeout: false */
10 |
11 | var requirejs, require, define;
12 | (function (undef) {
13 | var main, req, makeMap, handlers,
14 | defined = {},
15 | waiting = {},
16 | config = {},
17 | defining = {},
18 | hasOwn = Object.prototype.hasOwnProperty,
19 | aps = [].slice,
20 | jsSuffixRegExp = /\.js$/;
21 |
22 | function hasProp(obj, prop) {
23 | return hasOwn.call(obj, prop);
24 | }
25 |
26 | /**
27 | * Given a relative module name, like ./something, normalize it to
28 | * a real name that can be mapped to a path.
29 | * @param {String} name the relative name
30 | * @param {String} baseName a real name that the name arg is relative
31 | * to.
32 | * @returns {String} normalized name
33 | */
34 | function normalize(name, baseName) {
35 | var nameParts, nameSegment, mapValue, foundMap, lastIndex,
36 | foundI, foundStarMap, starI, i, j, part,
37 | baseParts = baseName && baseName.split("/"),
38 | map = config.map,
39 | starMap = (map && map['*']) || {};
40 |
41 | //Adjust any relative paths.
42 | if (name && name.charAt(0) === ".") {
43 | //If have a base name, try to normalize against it,
44 | //otherwise, assume it is a top-level require that will
45 | //be relative to baseUrl in the end.
46 | if (baseName) {
47 | //Convert baseName to array, and lop off the last part,
48 | //so that . matches that "directory" and not name of the baseName's
49 | //module. For instance, baseName of "one/two/three", maps to
50 | //"one/two/three.js", but we want the directory, "one/two" for
51 | //this normalization.
52 | baseParts = baseParts.slice(0, baseParts.length - 1);
53 | name = name.split('/');
54 | lastIndex = name.length - 1;
55 |
56 | // Node .js allowance:
57 | if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
58 | name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
59 | }
60 |
61 | name = baseParts.concat(name);
62 |
63 | //start trimDots
64 | for (i = 0; i < name.length; i += 1) {
65 | part = name[i];
66 | if (part === ".") {
67 | name.splice(i, 1);
68 | i -= 1;
69 | } else if (part === "..") {
70 | if (i === 1 && (name[2] === '..' || name[0] === '..')) {
71 | //End of the line. Keep at least one non-dot
72 | //path segment at the front so it can be mapped
73 | //correctly to disk. Otherwise, there is likely
74 | //no path mapping for a path starting with '..'.
75 | //This can still fail, but catches the most reasonable
76 | //uses of ..
77 | break;
78 | } else if (i > 0) {
79 | name.splice(i - 1, 2);
80 | i -= 2;
81 | }
82 | }
83 | }
84 | //end trimDots
85 |
86 | name = name.join("/");
87 | } else if (name.indexOf('./') === 0) {
88 | // No baseName, so this is ID is resolved relative
89 | // to baseUrl, pull off the leading dot.
90 | name = name.substring(2);
91 | }
92 | }
93 |
94 | //Apply map config if available.
95 | if ((baseParts || starMap) && map) {
96 | nameParts = name.split('/');
97 |
98 | for (i = nameParts.length; i > 0; i -= 1) {
99 | nameSegment = nameParts.slice(0, i).join("/");
100 |
101 | if (baseParts) {
102 | //Find the longest baseName segment match in the config.
103 | //So, do joins on the biggest to smallest lengths of baseParts.
104 | for (j = baseParts.length; j > 0; j -= 1) {
105 | mapValue = map[baseParts.slice(0, j).join('/')];
106 |
107 | //baseName segment has config, find if it has one for
108 | //this name.
109 | if (mapValue) {
110 | mapValue = mapValue[nameSegment];
111 | if (mapValue) {
112 | //Match, update name to the new value.
113 | foundMap = mapValue;
114 | foundI = i;
115 | break;
116 | }
117 | }
118 | }
119 | }
120 |
121 | if (foundMap) {
122 | break;
123 | }
124 |
125 | //Check for a star map match, but just hold on to it,
126 | //if there is a shorter segment match later in a matching
127 | //config, then favor over this star map.
128 | if (!foundStarMap && starMap && starMap[nameSegment]) {
129 | foundStarMap = starMap[nameSegment];
130 | starI = i;
131 | }
132 | }
133 |
134 | if (!foundMap && foundStarMap) {
135 | foundMap = foundStarMap;
136 | foundI = starI;
137 | }
138 |
139 | if (foundMap) {
140 | nameParts.splice(0, foundI, foundMap);
141 | name = nameParts.join('/');
142 | }
143 | }
144 |
145 | return name;
146 | }
147 |
148 | function makeRequire(relName, forceSync) {
149 | return function () {
150 | //A version of a require function that passes a moduleName
151 | //value for items that may need to
152 | //look up paths relative to the moduleName
153 | var args = aps.call(arguments, 0);
154 |
155 | //If first arg is not require('string'), and there is only
156 | //one arg, it is the array form without a callback. Insert
157 | //a null so that the following concat is correct.
158 | if (typeof args[0] !== 'string' && args.length === 1) {
159 | args.push(null);
160 | }
161 | return req.apply(undef, args.concat([relName, forceSync]));
162 | };
163 | }
164 |
165 | function makeNormalize(relName) {
166 | return function (name) {
167 | return normalize(name, relName);
168 | };
169 | }
170 |
171 | function makeLoad(depName) {
172 | return function (value) {
173 | defined[depName] = value;
174 | };
175 | }
176 |
177 | function callDep(name) {
178 | if (hasProp(waiting, name)) {
179 | var args = waiting[name];
180 | delete waiting[name];
181 | defining[name] = true;
182 | main.apply(undef, args);
183 | }
184 |
185 | if (!hasProp(defined, name) && !hasProp(defining, name)) {
186 | throw new Error('No ' + name);
187 | }
188 | return defined[name];
189 | }
190 |
191 | //Turns a plugin!resource to [plugin, resource]
192 | //with the plugin being undefined if the name
193 | //did not have a plugin prefix.
194 | function splitPrefix(name) {
195 | var prefix,
196 | index = name ? name.indexOf('!') : -1;
197 | if (index > -1) {
198 | prefix = name.substring(0, index);
199 | name = name.substring(index + 1, name.length);
200 | }
201 | return [prefix, name];
202 | }
203 |
204 | /**
205 | * Makes a name map, normalizing the name, and using a plugin
206 | * for normalization if necessary. Grabs a ref to plugin
207 | * too, as an optimization.
208 | */
209 | makeMap = function (name, relName) {
210 | var plugin,
211 | parts = splitPrefix(name),
212 | prefix = parts[0];
213 |
214 | name = parts[1];
215 |
216 | if (prefix) {
217 | prefix = normalize(prefix, relName);
218 | plugin = callDep(prefix);
219 | }
220 |
221 | //Normalize according
222 | if (prefix) {
223 | if (plugin && plugin.normalize) {
224 | name = plugin.normalize(name, makeNormalize(relName));
225 | } else {
226 | name = normalize(name, relName);
227 | }
228 | } else {
229 | name = normalize(name, relName);
230 | parts = splitPrefix(name);
231 | prefix = parts[0];
232 | name = parts[1];
233 | if (prefix) {
234 | plugin = callDep(prefix);
235 | }
236 | }
237 |
238 | //Using ridiculous property names for space reasons
239 | return {
240 | f: prefix ? prefix + '!' + name : name, //fullName
241 | n: name,
242 | pr: prefix,
243 | p: plugin
244 | };
245 | };
246 |
247 | function makeConfig(name) {
248 | return function () {
249 | return (config && config.config && config.config[name]) || {};
250 | };
251 | }
252 |
253 | handlers = {
254 | require: function (name) {
255 | return makeRequire(name);
256 | },
257 | exports: function (name) {
258 | var e = defined[name];
259 | if (typeof e !== 'undefined') {
260 | return e;
261 | } else {
262 | return (defined[name] = {});
263 | }
264 | },
265 | module: function (name) {
266 | return {
267 | id: name,
268 | uri: '',
269 | exports: defined[name],
270 | config: makeConfig(name)
271 | };
272 | }
273 | };
274 |
275 | main = function (name, deps, callback, relName) {
276 | var cjsModule, depName, ret, map, i,
277 | args = [],
278 | callbackType = typeof callback,
279 | usingExports;
280 |
281 | //Use name if no relName
282 | relName = relName || name;
283 |
284 | //Call the callback to define the module, if necessary.
285 | if (callbackType === 'undefined' || callbackType === 'function') {
286 | //Pull out the defined dependencies and pass the ordered
287 | //values to the callback.
288 | //Default to [require, exports, module] if no deps
289 | deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
290 | for (i = 0; i < deps.length; i += 1) {
291 | map = makeMap(deps[i], relName);
292 | depName = map.f;
293 |
294 | //Fast path CommonJS standard dependencies.
295 | if (depName === "require") {
296 | args[i] = handlers.require(name);
297 | } else if (depName === "exports") {
298 | //CommonJS module spec 1.1
299 | args[i] = handlers.exports(name);
300 | usingExports = true;
301 | } else if (depName === "module") {
302 | //CommonJS module spec 1.1
303 | cjsModule = args[i] = handlers.module(name);
304 | } else if (hasProp(defined, depName) ||
305 | hasProp(waiting, depName) ||
306 | hasProp(defining, depName)) {
307 | args[i] = callDep(depName);
308 | } else if (map.p) {
309 | map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
310 | args[i] = defined[depName];
311 | } else {
312 | throw new Error(name + ' missing ' + depName);
313 | }
314 | }
315 |
316 | ret = callback ? callback.apply(defined[name], args) : undefined;
317 |
318 | if (name) {
319 | //If setting exports via "module" is in play,
320 | //favor that over return value and exports. After that,
321 | //favor a non-undefined return value over exports use.
322 | if (cjsModule && cjsModule.exports !== undef &&
323 | cjsModule.exports !== defined[name]) {
324 | defined[name] = cjsModule.exports;
325 | } else if (ret !== undef || !usingExports) {
326 | //Use the return value from the function.
327 | defined[name] = ret;
328 | }
329 | }
330 | } else if (name) {
331 | //May just be an object definition for the module. Only
332 | //worry about defining if have a module name.
333 | defined[name] = callback;
334 | }
335 | };
336 |
337 | requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
338 | if (typeof deps === "string") {
339 | if (handlers[deps]) {
340 | //callback in this case is really relName
341 | return handlers[deps](callback);
342 | }
343 | //Just return the module wanted. In this scenario, the
344 | //deps arg is the module name, and second arg (if passed)
345 | //is just the relName.
346 | //Normalize module name, if it contains . or ..
347 | return callDep(makeMap(deps, callback).f);
348 | } else if (!deps.splice) {
349 | //deps is a config object, not an array.
350 | config = deps;
351 | if (config.deps) {
352 | req(config.deps, config.callback);
353 | }
354 | if (!callback) {
355 | return;
356 | }
357 |
358 | if (callback.splice) {
359 | //callback is an array, which means it is a dependency list.
360 | //Adjust args if there are dependencies
361 | deps = callback;
362 | callback = relName;
363 | relName = null;
364 | } else {
365 | deps = undef;
366 | }
367 | }
368 |
369 | //Support require(['a'])
370 | callback = callback || function () {};
371 |
372 | //If relName is a function, it is an errback handler,
373 | //so remove it.
374 | if (typeof relName === 'function') {
375 | relName = forceSync;
376 | forceSync = alt;
377 | }
378 |
379 | //Simulate async callback;
380 | if (forceSync) {
381 | main(undef, deps, callback, relName);
382 | } else {
383 | //Using a non-zero value because of concern for what old browsers
384 | //do, and latest browsers "upgrade" to 4 if lower value is used:
385 | //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
386 | //If want a value immediately, use require('id') instead -- something
387 | //that works in almond on the global level, but not guaranteed and
388 | //unlikely to work in other AMD implementations.
389 | setTimeout(function () {
390 | main(undef, deps, callback, relName);
391 | }, 4);
392 | }
393 |
394 | return req;
395 | };
396 |
397 | /**
398 | * Just drops the config on the floor, but returns req in case
399 | * the config return value is used.
400 | */
401 | req.config = function (cfg) {
402 | return req(cfg);
403 | };
404 |
405 | /**
406 | * Expose module registry for debugging and tooling
407 | */
408 | requirejs._defined = defined;
409 |
410 | define = function (name, deps, callback) {
411 |
412 | //This module may not have dependencies
413 | if (!deps.splice) {
414 | //deps is not an array, so probably means
415 | //an object literal or factory function for
416 | //the value. Adjust args.
417 | callback = deps;
418 | deps = [];
419 | }
420 |
421 | if (!hasProp(defined, name) && !hasProp(waiting, name)) {
422 | waiting[name] = [name, deps, callback];
423 | }
424 | };
425 |
426 | define.amd = {
427 | jQuery: true
428 | };
429 | }());
430 |
--------------------------------------------------------------------------------
/btscale.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0) {
101 | if (handlers.length === 1)
102 | delete this.listeners_[type];
103 | else
104 | handlers.splice(index, 1);
105 | }
106 | }
107 | };
108 | BTSEventTarget.prototype.dispatchEvent = function (event) {
109 | if (!this.listeners_)
110 | return true;
111 | var self = this;
112 | event.__defineGetter__('target', function () {
113 | return self;
114 | });
115 | var type = event.type;
116 | var prevented = 0;
117 | if (type in this.listeners_) {
118 | var handlers = this.listeners_[type].concat();
119 | for (var i = 0, handler = void 0; (handler = handlers[i]); i++) {
120 | if (handler.handleEvent)
121 | prevented |= (handler.handleEvent.call(handler, event) === false);
122 | else
123 | prevented |= (handler.call(this, event) === false);
124 | }
125 | }
126 | return !prevented && !event.defaultPrevented;
127 | };
128 | return BTSEventTarget;
129 | })();
130 | exports.BTSEventTarget = BTSEventTarget;
131 |
132 | },{}],3:[function(require,module,exports){
133 | 'use strict';
134 | var constants_1 = require('./constants');
135 | var MAX_PAYLOAD_LENGTH = 10;
136 | var sequenceId = 0;
137 | function nextSequenceId() {
138 | var next = sequenceId++;
139 | sequenceId &= 0xff;
140 | return next;
141 | }
142 | function setSequenceId(id) {
143 | sequenceId = id & 0xff;
144 | }
145 | exports.setSequenceId = setSequenceId;
146 | function getSequenceId() {
147 | return sequenceId;
148 | }
149 | var Message = (function () {
150 | function Message(type, id, payload) {
151 | this.type = type;
152 | this.id = id;
153 | this.payload = payload;
154 | this.value = null;
155 | if (type === 5) {
156 | var value = ((payload[1] & 0xff) << 8) + (payload[0] & 0xff);
157 | for (var i = 0; i < payload[4]; i++)
158 | value /= 10;
159 | if ((payload[6] & 0x02) === 0x02)
160 | value *= -1;
161 | this.value = value;
162 | }
163 | }
164 | return Message;
165 | })();
166 | exports.Message = Message;
167 | function encipher(out, input, sequenceId) {
168 | for (var i = 0; i < out.byteLength; i++) {
169 | var offset = (input[i] + sequenceId) & 0xff;
170 | out[i] = constants_1.TABLE1[offset];
171 | }
172 | }
173 | function decipher(input, sequenceId) {
174 | var result = new Uint8Array(input.byteLength);
175 | for (var i = 0; i < input.byteLength; i++) {
176 | var offset = input[i] & 0xff;
177 | result[i] = (constants_1.TABLE2[offset] - sequenceId) & 0xff;
178 | }
179 | return result;
180 | }
181 | function checksum(data) {
182 | var sum = 0;
183 | for (var i = 0; i < data.length; i++)
184 | sum += data[i];
185 | return sum & 0xff;
186 | }
187 | function encode(msgType, id, payload) {
188 | if (payload.length > MAX_PAYLOAD_LENGTH)
189 | throw 'payload too long: ' + payload.length;
190 | var buf = new ArrayBuffer(8 + payload.length);
191 | var bytes = new Uint8Array(buf);
192 | var sequenceId = nextSequenceId();
193 | bytes[0] = constants_1.MAGIC1;
194 | bytes[1] = constants_1.MAGIC2;
195 | bytes[2] = 5 + payload.length;
196 | bytes[3] = msgType;
197 | bytes[4] = sequenceId;
198 | bytes[5] = id;
199 | bytes[6] = payload.length & 0xff;
200 | var payloadOut = new Uint8Array(buf, 7, payload.length);
201 | encipher(payloadOut, payload, sequenceId);
202 | var contentsToChecksum = new Uint8Array(buf, 3, payload.length + 4);
203 | bytes[7 + payload.length] = checksum(contentsToChecksum);
204 | return buf;
205 | }
206 | function decode(data) {
207 | var len = data.byteLength;
208 | if (!len)
209 | return;
210 | var bytes = new Uint8Array(data);
211 | if (len < 8)
212 | throw 'data too short: ' + len;
213 | if (bytes[0] !== constants_1.MAGIC1 && bytes[1] !== constants_1.MAGIC2)
214 | throw "don't have the magic";
215 | var len1 = bytes[2];
216 | var contentsToChecksum = new Uint8Array(data.slice(3, len - 1));
217 | var cs = checksum(contentsToChecksum);
218 | if (bytes[len - 1] !== cs)
219 | throw 'checksum mismatch ' + bytes[len - 1] + ' !== ' + cs;
220 | var msgType = bytes[3];
221 | var sequenceId = bytes[4];
222 | var id = bytes[5];
223 | var len2 = bytes[6];
224 | if (len1 !== len - 3)
225 | throw 'length mismatch 1 ' + len1 + ' !== ' + (len - 3);
226 | if (len2 !== len - 8)
227 | throw 'length mismatch 2';
228 | var payloadIn = new Uint8Array(data.slice(7, len - 1));
229 | var payload = decipher(payloadIn, sequenceId);
230 | return new Message(msgType, id, payload);
231 | }
232 | exports.decode = decode;
233 | function encodeWeight(period, time, type) {
234 | if (period === void 0) { period = 1; }
235 | if (time === void 0) { time = 100; }
236 | if (type === void 0) { type = 1; }
237 | var payload = [period & 0xff, time & 0xff, type & 0xff];
238 | return encode(4, 0, payload);
239 | }
240 | exports.encodeWeight = encodeWeight;
241 | function encodeTare() {
242 | var payload = [0x0, 0x0];
243 | return encode(12, 0, payload);
244 | }
245 | exports.encodeTare = encodeTare;
246 | function encodeStartTimer() {
247 | var payload = [0x5];
248 | return encode(12, 0, payload);
249 | }
250 | exports.encodeStartTimer = encodeStartTimer;
251 | function encodePauseTimer() {
252 | var payload = [0x6];
253 | return encode(12, 0, payload);
254 | }
255 | exports.encodePauseTimer = encodePauseTimer;
256 | function encodeStopTimer() {
257 | var payload = [0x7];
258 | return encode(12, 0, payload);
259 | }
260 | exports.encodeStopTimer = encodeStopTimer;
261 | function encodeGetTimer(count) {
262 | if (count === void 0) { count = 20; }
263 | var payload = [0x8, count & 0xff];
264 | return encode(12, 0, payload);
265 | }
266 | exports.encodeGetTimer = encodeGetTimer;
267 | function encodeGetBattery() {
268 | return encode(2, 0, []);
269 | }
270 | exports.encodeGetBattery = encodeGetBattery;
271 |
272 | },{"./constants":1}],4:[function(require,module,exports){
273 | 'use strict';
274 | var Recorder = (function () {
275 | function Recorder(scale) {
276 | this.start = Date.now() / 1000;
277 | this.series = [];
278 | this.scale = scale;
279 | this.recordCb = this.record.bind(this);
280 | this.record();
281 | scale.addEventListener('weightMeasured', this.recordCb);
282 | }
283 | Recorder.prototype.stop = function () {
284 | this.record();
285 | this.scale.removeEventListener('weightMeasured', this.recordCb);
286 | this.scale = null;
287 | this.recordCb = null;
288 | return this.series;
289 | };
290 | Recorder.prototype.record = function () {
291 | var time = Date.now() / 1000 - this.start;
292 | this.series.push([time, this.scale.weight]);
293 | };
294 | return Recorder;
295 | })();
296 | exports.Recorder = Recorder;
297 |
298 | },{}],5:[function(require,module,exports){
299 | 'use strict';
300 | var __extends = (this && this.__extends) || function (d, b) {
301 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
302 | function __() { this.constructor = d; }
303 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
304 | };
305 | var constants_1 = require('./constants');
306 | var event_target_1 = require('./event_target');
307 | var recorder_1 = require('./recorder');
308 | var packet = require('./packet');
309 | var Scale = (function (_super) {
310 | __extends(Scale, _super);
311 | function Scale(device) {
312 | _super.call(this);
313 | this.connected = false;
314 | this.service = null;
315 | this.characteristic = null;
316 | this.weight = null;
317 | this.recorder = null;
318 | this.batteryCb = null;
319 | this.series = null;
320 | this.device = device;
321 | this.name = this.device.name;
322 | console.log('created scale for ' + this.device.address + ' (' + this.device.name + ')');
323 | this.connect();
324 | }
325 | Scale.prototype.connect = function () {
326 | var _this = this;
327 | if (this.connected)
328 | return;
329 | var log = console.log.bind(console);
330 | this.device.gatt.connect()
331 | .then(function (server) {
332 | return _this.device.gatt.getPrimaryService(constants_1.SCALE_SERVICE_UUID);
333 | }, function (err) {
334 | console.log('error connecting - ' + err);
335 | return null;
336 | }).then(function (service) {
337 | _this.service = service;
338 | console.log('primary services ');
339 | return service.getCharacteristic(constants_1.SCALE_CHARACTERISTIC_UUID);
340 | }, function (err) {
341 | console.log('primary services ERR - ' + err);
342 | debugger;
343 | }).then(function (characteristic) {
344 | log('Starting notifications...');
345 | _this.characteristic = characteristic;
346 | return characteristic.startNotifications();
347 | }, function (err) {
348 | console.log('err getting characteristic');
349 | debugger;
350 | }).then(function (characteristic) {
351 | characteristic.addEventListener('characteristicvaluechanged', _this.characteristicValueChanged.bind(_this));
352 | _this.notificationsReady();
353 | }, function (err) {
354 | log('FAILED: ' + err);
355 | debugger;
356 | });
357 | };
358 | Scale.prototype.characteristicValueChanged = function (event) {
359 | var msg = packet.decode(event.target.value.buffer);
360 | if (!msg) {
361 | console.log('characteristic value update, but no message');
362 | return;
363 | }
364 | if (msg.type === 5) {
365 | var prevWeight = this.weight;
366 | var shouldDispatchChanged = this.weight !== msg.value;
367 | this.weight = msg.value;
368 | var detail = { 'detail': { 'value': msg.value, 'previous': prevWeight } };
369 | this.dispatchEvent(new CustomEvent('weightMeasured', detail));
370 | if (shouldDispatchChanged)
371 | this.dispatchEvent(new CustomEvent('weightChanged', detail));
372 | }
373 | else if (msg.type === 3) {
374 | var cb = this.batteryCb;
375 | this.batteryCb = null;
376 | if (cb)
377 | cb(msg.payload[0] / 100);
378 | }
379 | else {
380 | console.log('non-weight response');
381 | console.log(msg);
382 | }
383 | };
384 | Scale.prototype.disconnect = function () {
385 | this.connected = false;
386 | if (this.device)
387 | this.device.gatt.connect();
388 | };
389 | Scale.prototype.notificationsReady = function () {
390 | console.log('scale ready');
391 | this.connected = true;
392 | this.poll();
393 | setInterval(this.poll.bind(this), 1000);
394 | this.dispatchEvent(new CustomEvent('ready', { 'detail': { 'scale': this } }));
395 | };
396 | Scale.prototype.tare = function () {
397 | if (!this.connected)
398 | return false;
399 | var msg = packet.encodeTare();
400 | this.characteristic.writeValue(msg)
401 | .then(function () {
402 | }, function (err) {
403 | console.log('write failed: ' + err);
404 | });
405 | return true;
406 | };
407 | Scale.prototype.startTimer = function () {
408 | if (!this.connected)
409 | return false;
410 | var msg = packet.encodeStartTimer();
411 | this.characteristic.writeValue(msg)
412 | .then(function () {
413 | }, function (err) {
414 | console.log('write failed: ' + err);
415 | });
416 | return true;
417 | };
418 | Scale.prototype.pauseTimer = function () {
419 | if (!this.connected)
420 | return false;
421 | var msg = packet.encodePauseTimer();
422 | this.characteristic.writeValue(msg)
423 | .then(function () {
424 | }, function (err) {
425 | console.log('write failed: ' + err);
426 | });
427 | return true;
428 | };
429 | Scale.prototype.stopTimer = function () {
430 | if (!this.connected)
431 | return false;
432 | var msg = packet.encodeStopTimer();
433 | this.characteristic.writeValue(msg)
434 | .then(function () {
435 | }, function (err) {
436 | console.log('write failed: ' + err);
437 | });
438 | return true;
439 | };
440 | ;
441 | Scale.prototype.getTimer = function (count) {
442 | if (!this.connected)
443 | return false;
444 | if (!count)
445 | count = 1;
446 | var msg = packet.encodeGetTimer(count);
447 | this.characteristic.writeValue(msg)
448 | .then(function () {
449 | }, function (err) {
450 | console.log('write failed: ' + err);
451 | });
452 | return true;
453 | };
454 | Scale.prototype.getBattery = function (cb) {
455 | if (!this.connected)
456 | return false;
457 | this.batteryCb = cb;
458 | var msg = packet.encodeGetBattery();
459 | this.characteristic.writeValue(msg)
460 | .then(function () {
461 | }, function (err) {
462 | console.log('write failed: ' + err);
463 | });
464 | return true;
465 | };
466 | Scale.prototype.poll = function () {
467 | if (!this.connected)
468 | return false;
469 | var msg = packet.encodeWeight();
470 | this.characteristic.writeValue(msg)
471 | .then(function () {
472 | }, function (err) {
473 | console.log('write failed: ' + err);
474 | });
475 | return true;
476 | };
477 | Scale.prototype.startRecording = function () {
478 | if (this.recorder)
479 | return;
480 | this.recorder = new recorder_1.Recorder(this);
481 | };
482 | Scale.prototype.stopRecording = function () {
483 | this.series = this.recorder.stop();
484 | this.recorder = null;
485 | return this.series;
486 | };
487 | return Scale;
488 | })(event_target_1.BTSEventTarget);
489 | exports.Scale = Scale;
490 |
491 | },{"./constants":1,"./event_target":2,"./packet":3,"./recorder":4}],6:[function(require,module,exports){
492 | 'use strict';
493 | var __extends = (this && this.__extends) || function (d, b) {
494 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
495 | function __() { this.constructor = d; }
496 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
497 | };
498 | var constants_1 = require('./constants');
499 | var event_target_1 = require('./event_target');
500 | var scale_1 = require('./scale');
501 | var bluetooth = navigator.bluetooth;
502 | var ScaleFinder = (function (_super) {
503 | __extends(ScaleFinder, _super);
504 | function ScaleFinder() {
505 | _super.call(this);
506 | this.ready = false;
507 | this.devices = {};
508 | this.scales = [];
509 | this.adapterState = null;
510 | this.failed = false;
511 | console.log('new ScaleFinder');
512 | }
513 | ScaleFinder.prototype.deviceAdded = function (device) {
514 | if (device.address in this.devices) {
515 | console.log('WARN: device added that is already known ' + device.address);
516 | return;
517 | }
518 | var scale = new scale_1.Scale(device);
519 | this.devices[device.address] = scale;
520 | this.scales.push(scale);
521 | };
522 | ScaleFinder.prototype.startDiscovery = function () {
523 | var _this = this;
524 | if (this.failed)
525 | return;
526 | bluetooth.requestDevice({ filters: [{ services: [constants_1.SCALE_SERVICE_UUID] }] })
527 | .then(function (device) {
528 | _this.deviceAdded(device);
529 | });
530 | };
531 | ScaleFinder.prototype.stopDiscovery = function () {
532 | if (this.failed)
533 | return;
534 | };
535 | return ScaleFinder;
536 | })(event_target_1.BTSEventTarget);
537 | exports.ScaleFinder = ScaleFinder;
538 | if (typeof window !== 'undefined')
539 | window.ScaleFinder = ScaleFinder;
540 |
541 | },{"./constants":1,"./event_target":2,"./scale":5}]},{},[6]);
542 |
--------------------------------------------------------------------------------