Skip to content
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

Automatically command rotator when tuning database entries #122

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
dropin.cache
_trial_temp*/

# our files
/shinysdr/deps/
# Non-git deps
/shinysdr/deps/require.js
/shinysdr/deps/text.js

# GRC-generated
shinysdr/test/manual/channel_filter_testbed.py
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "shinysdr/deps/measviz"]
path = shinysdr/deps/measviz
url = https://github.com/kpreid/measviz/
[submodule "shinysdr/deps/geodesy"]
path = shinysdr/deps/geodesy
url = https://github.com/chrisveness/geodesy
1 change: 1 addition & 0 deletions shinysdr/deps/geodesy
Submodule geodesy added at 2c8900
75 changes: 71 additions & 4 deletions shinysdr/i/network/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from __future__ import absolute_import, division, print_function, unicode_literals

import StringIO
import os

import six
Expand Down Expand Up @@ -48,9 +49,9 @@
from shinysdr.values import SubscriptionContext


def _make_static_resource(pathname):
def _make_static_resource(pathname, cls=static.File):
# str() because if we happen to pass unicode as the pathname then directory listings break (discovered with Twisted 16.4.1).
r = static.File(str(pathname),
r = cls(str(pathname),
defaultType=b'text/plain',
ignoredExts=[b'.html'])
r.contentTypes[b'.csv'] = b'text/csv'
Expand Down Expand Up @@ -172,6 +173,66 @@ def announce(self, open_client):
self.__log.info('Visit {url}', url=url)


class ConcatenatedReaders(object):
def __init__(self, files):
self.__files = files
self.__current_file = 0

def seek(self, offset):
for i, f in enumerate(self.__files):
f.seek(0, os.SEEK_END)
length = f.tell()
if offset > length:
offset -= length
continue
f.seek(offset, os.SEEK_SET)
self.__current_file = i
return

def read(self, n=-1):
out = defaultstr("")
while n != 0 and self.__current_file < len(self.__files):
part = self.__files[self.__current_file].read(n)
out += part
if n < 0 or len(part) < n:
self.__current_file += 1
if self.__current_file < len(self.__files):
self.__files[self.__current_file].seek(0, os.SEEK_SET)
n -= len(part)
return out

def close(self):
for f in self.__files:
f.close()


class WrappedStaticFile(static.File):
prefix = ""
suffix = ""

def openForReading(self):
f = self.open()
return ConcatenatedReaders([
StringIO.StringIO(defaultstr(self.prefix)),
f,
StringIO.StringIO(defaultstr(self.suffix)),
])

def getFileSize(self):
return len(self.prefix) + self.getsize() + len(self.suffix)


class CommonJSStaticFile(WrappedStaticFile):
"""
Serves a CommonJS-style source file with a RequireJS wrapper.
"""
prefix = """define(function (require, exports, module) {
"""
suffix = """
});
"""


def _put_root_static(wcommon, container_resource):
"""Place all the simple resources, that are not necessarily sourced from files but at least are unchanging and public."""

Expand All @@ -184,6 +245,12 @@ def _put_root_static(wcommon, container_resource):
client.putChild(name, _make_static_resource(os.path.join(deps_path, name)))
for name in ['measviz.js', 'measviz.css']:
client.putChild(name, _make_static_resource(os.path.join(deps_path, 'measviz/src', name)))
geodesy = SlashedResource()
client.putChild('geodesy', geodesy)
for name in ['latlon-spherical.js', 'dms.js']:
geodesy.putChild(name, _make_static_resource(
os.path.join(deps_path, 'geodesy', name),
CommonJSStaticFile))

# Link deps into /test/.
test = container_resource.children['test']
Expand Down Expand Up @@ -211,11 +278,11 @@ def _put_plugin_resources(client_resource):
for resource_def in getPlugins(_IClientResourceDef, shinysdr.plugins):
# Add the plugin's resource to static serving
plugin_resources.putChild(resource_def.key, resource_def.resource)
plugin_resource_url = '/client/plugins/' + urllib.parse.quote(resource_def.key, safe='') + '/'
plugin_resource_url = 'plugins/' + urllib.parse.quote(resource_def.key, safe='') + '/'
# Tell the client to load the plugins
# TODO constrain path values to be relative (not on a different origin, to not leak urls)
if resource_def.load_css_path is not None:
load_list_css.append(plugin_resource_url + resource_def.load_cs_path)
load_list_css.append('/client/' + plugin_resource_url + resource_def.load_cs_path)
if resource_def.load_js_path is not None:
# TODO constrain value to be in the directory
load_list_js.append(plugin_resource_url + resource_def.load_js_path)
Expand Down
1 change: 1 addition & 0 deletions shinysdr/i/webparts/block.template.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'use strict';
requirejs.config({
baseUrl: "/client",
nodeIdCompat: true,
});
requirejs(['main'], function (main) {
main({
Expand Down
1 change: 1 addition & 0 deletions shinysdr/i/webparts/index.template.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
'use strict';
requirejs.config({
baseUrl: "/client",
nodeIdCompat: true,
});
requirejs(['main'], function (main) {
main({
Expand Down
30 changes: 29 additions & 1 deletion shinysdr/i/webstatic/client/coordination.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

define([
'require',
'geodesy/latlon-spherical',
'./types',
'./values',
], (
require,
LatLon,
import_types,
import_values
) => {
Expand All @@ -36,6 +38,7 @@ define([
ConstantCell,
LocalCell,
StorageCell,
findImplementersInBlockCell,
makeBlock,
} = import_values;

Expand Down Expand Up @@ -115,7 +118,32 @@ define([
// (This will require knowledge of retuning which is currently done implicitly on the server side.)

if (record) {
// TODO: The server really needs to track the selected record because both the source and the record can move, and something needs to constantly recalculate the bearing and drive the rotator.
// TODO: Provide a way for the user to disable this (e.g. in EME).
selectedRecord.set(record);
if (record.location) {
const componentsCell = radio.source.get().components;
const positionedDevices = findImplementersInBlockCell(
undefined,
componentsCell,
'shinysdr.devices.IPositionedDevice').get();
const rotators = findImplementersInBlockCell(
undefined,
componentsCell,
'shinysdr.plugins.hamlib.IRotator').get();
if (positionedDevices.length && rotators.length) {
const track = positionedDevices[0].track.get();
const start = new LatLon(track.latitude.value, track.longitude.value);
let bearing = start.bearingTo(new LatLon(record.location[0], record.location[1]));
rotators.forEach(rotator => {
// TODO: It doesn't seem like I should have to do this here; the azimuth cell should know how to unwrap bearings.
if (bearing > rotator.Azimuth.type.getMax()) {
bearing -= 360;
}
rotator.Azimuth.set(bearing);
});
}
}
}

return receiver;
Expand Down Expand Up @@ -172,4 +200,4 @@ define([
exports.ClientStateObject = ClientStateObject;

return Object.freeze(exports);
});
});
20 changes: 7 additions & 13 deletions shinysdr/i/webstatic/client/map/map-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

define([
'require',
'geodesy/latlon-spherical',
'../domtools',
'../events',
'../gltools',
Expand All @@ -34,6 +35,7 @@ define([
'text!./curves-f.glsl',
], (
require,
LatLon,
import_domtools,
import_events,
import_gltools,
Expand Down Expand Up @@ -91,7 +93,6 @@ define([
const {
cos,
sin,
asin,
atan2
} = Math;

Expand All @@ -100,10 +101,10 @@ define([
// Degree trig functions.
// We use degrees in this module because degrees are standard for latitude and longitude, and are also useful for more exact calculations because 360 is exactly representable as a floating-point number whereas 2π is not.
// TODO: Look at the edge cases and see if it would be useful to have dcos & dsin do modulo 360, so we get that exactness for them.
var RADIANS_PER_DEGREE = Math.PI / 180;
const RADIANS_PER_DEGREE = Math.PI / 180;
const DEGREES_PER_RADIAN = 180 / Math.PI;
function dcos(x) { return cos(RADIANS_PER_DEGREE * x); }
function dsin(x) { return sin(RADIANS_PER_DEGREE * x); }
function dasin(x) { return asin(x)/RADIANS_PER_DEGREE; }
function datan2(x, y) { return atan2(x, y)/RADIANS_PER_DEGREE; }

function mean(array) {
Expand Down Expand Up @@ -1692,17 +1693,10 @@ define([
const smoothStep = 1;
function greatCircleLineAlong(lat, lon, bearing) {
const line = [];
const sinlat = dsin(lat), coslat = dcos(lat);
const sinazimuth = dsin(bearing), cosazimuth = dcos(bearing);
const start = new LatLon(lat, lon);
for (let angle = 0; angle < 180 + smoothStep/2; angle += smoothStep) {
// Algorithm adapted from https://github.com/chrisveness/geodesy/blob/v1.1.2/latlon-spherical.js#L212
const targetLat = dasin(
sinlat*dcos(angle) +
coslat*dsin(angle)*cosazimuth);
const targetLon = lon + datan2(
sinazimuth*dsin(angle)*coslat,
dcos(angle)-sinlat*dsin(targetLat));
line.push(Object.freeze({position: Object.freeze([targetLat, targetLon])}));
const point = start.destinationPoint(angle, bearing, DEGREES_PER_RADIAN);
line.push(Object.freeze({position: Object.freeze([point.lat, point.lon])}));
}
return Object.freeze(line);
}
Expand Down
18 changes: 11 additions & 7 deletions shinysdr/i/webstatic/test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,20 @@
</head><body>
<script>
require.config({
baseUrl: '/client/'
baseUrl: '/client/',
paths: {
'test': '/test',
},
nodeIdCompat: true,
});
requirejs(['network', '/test/jasmine-glue.js',], (network, {ji, start}) => {

requirejs(['network', 'test/jasmine-glue',], (network, {ji, start}) => {
network.externalGet('t/', 'document').then(indexDoc => {
const testUrls = [];
Array.prototype.forEach.call(indexDoc.querySelectorAll('a[href]'), anchor => {
var url = anchor.href;
if (/\/test_.*\.js$/.test(url)) {
testUrls.push(url);
var url = anchor.getAttribute('href');
if (/^test_.*\.js$/.test(url)) {
testUrls.push('test/t/' + url);
}
});
requirejs(testUrls, (...results) => {
Expand All @@ -55,4 +59,4 @@
});
});
</script>
</body></html>
</body></html>
4 changes: 2 additions & 2 deletions shinysdr/i/webstatic/test/t/test_audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
'use strict';

define([
'/test/jasmine-glue.js',
'test/jasmine-glue',
'audio/analyser',
'audio/bufferer',
'audio/client-source',
Expand Down Expand Up @@ -256,4 +256,4 @@ define([
});

return 'ok';
});
});
4 changes: 2 additions & 2 deletions shinysdr/i/webstatic/test/t/test_coordination.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
'use strict';

define([
'/test/jasmine-glue.js',
'test/jasmine-glue',
'coordination',
'database',
'values'
Expand Down Expand Up @@ -71,4 +71,4 @@ define([
});

return 'ok';
});
});
4 changes: 2 additions & 2 deletions shinysdr/i/webstatic/test/t/test_database.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
'use strict';

define([
'/test/jasmine-glue.js',
'/test/testutil.js',
'test/jasmine-glue',
'test/testutil',
'database',
'events',
], (
Expand Down
4 changes: 2 additions & 2 deletions shinysdr/i/webstatic/test/t/test_domtools.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
'use strict';

define([
'/test/jasmine-glue.js',
'test/jasmine-glue',
'domtools',
], (
import_jasmine,
Expand Down Expand Up @@ -158,4 +158,4 @@ define([
});

return 'ok';
});
});
4 changes: 2 additions & 2 deletions shinysdr/i/webstatic/test/t/test_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
'use strict';

define([
'/test/jasmine-glue.js',
'test/jasmine-glue',
'events',
], (
import_jasmine,
Expand Down Expand Up @@ -218,4 +218,4 @@ define([
});

return 'ok';
});
});
6 changes: 3 additions & 3 deletions shinysdr/i/webstatic/test/t/test_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
'use strict';

define([
'/test/jasmine-glue.js',
'/test/testutil.js',
'test/jasmine-glue',
'test/testutil',
'map/map-core',
'types',
'values',
Expand Down Expand Up @@ -149,4 +149,4 @@ define([
});

return 'ok';
});
});
Loading