在ionic中使用ibeacon

在ionic中使用ibeacon,和native开发中的步骤几乎一致,只需以下几步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//指定ibeacon的uuid和identifier,这些需要提前在ibeacon中配置好
var uuid = 'SD041XAE-152C-43F5-A7W8-4F7ED54E6DA9'
var identifier = 'myibeacon'

//创建locationManager代理
var delegate = new cordova.plugins.locationManager.Delegate()
cordova.plugins.locationManager.setDelegate(delegate);

//开始监听ibeacon事件
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid)
cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion)
.fail(console.error)
.done();
cordova.plugins.locationManager.startRangingBeaconsInRegion(beaconRegion)
.fail(console.error)
.done();

// required in iOS 8+
cordova.plugins.locationManager.requestAlwaysAuthorization()

//获取ibeacon监听事件
delegate.didRangeBeaconsInRegion = function(pluginResult) {
console.log(pluginResult.beacons)
}

实现最短路径查找服务端api

实现最短路径查找,需要服务端配合:
以ruby为例,首先创建一个私有方法,用来获取“附近”的node,作为开始位置和结束位置

1
2
3
4
5
6
7
8
9
10
11
12
def find_closest_network_node(x, y, floor)
res = CONN.execute(%Q{SELECT verts.id as id FROM public.networklines_3857_vertices_pgr AS verts
INNER JOIN (select ST_PointFromText('POINT(#{x} #{y} #{floor})', 3857)as geom) AS pt
ON ST_DWithin(verts.the_geom, pt.geom, 100.0)
WHERE ST_Z(verts.the_geom) = #{floor}
ORDER BY ST_3DDistance(verts.the_geom, pt.geom) LIMIT 1})
if res.ntuples != 0
res.getvalue(0,0)
else
return false
end
end

建立坐标系转换私有方法:

1
2
3
4
5
6
def unproject(lon, lat)
src_prj = RGeo::CoordSys::Proj4.new("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs")
dest_prj = RGeo::CoordSys::Proj4.new("+proj=longlat +datum=WGS84 +no_defs")
point = RGeo::CoordSys::Proj4::transform_coords(src_prj, dest_prj, lon, lat)
{x: point[0], y: point[1]}
end

然后创建获取最短路径的geoJSON,以供前台展示用,比如leaflet等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def map_path
start_x = params[:start_x]
start_y = params[:start_y]
start_floor = Beacon.find_by_name(params[:start_minor].to_i).floor.num

end_x = params[:end_x]
end_y = params[:end_y]
end_floor = Beacon.find_by_name(params[:end_minor].to_i).floor.num

//获取开始位置和结束位置的node id
start_node_id = find_closest_network_node(start_x, start_y, start_floor)
end_node_id = find_closest_network_node(end_x, end_y, end_floor)

//通过数据库查询最短路径的拓扑数据,指定返回的拓扑结果为geoJSON格式
if start_node_id.present? && end_node_id.present?
res = CONN.execute(%Q{SELECT seq, id1 AS node, id2 AS edge,
total_cost AS cost, layer,
type_id, ST_AsGeoJSON(wkb_geometry) AS geoj
FROM pgr_dijkstra(
'SELECT ogc_fid as id, source, target,
st_length(wkb_geometry) AS cost,
layer, type_id
FROM public.networklines_3857',

#{start_node_id}, #{end_node_id}, FALSE, FALSE
) AS dij_route
JOIN public.networklines_3857 AS input_network
ON dij_route.id2 = input_network.ogc_fid})
else
return render nothing: true, status: 404
end

//拼装成leaflet所用的格式返回给客户端
route_features = []

res.each do |segment|

seg_cost = segment['cost'] # cost value
layer_level = segment['layer'].to_i # floor number
seg_type = segment['type_id']
geojs = JSON.parse(segment['geoj']) # geojson coordinates


geojs["coordinates"].each do |geo|
lon = geo[0]
lat = geo[1]
point = unproject(lon, lat)
geo[0] = point[:x]
geo[1] = point[:y]
end

# build geojson
feature = { "type": "Feature",
"geometry": geojs,
"properties": {"floor": layer_level,
"length": seg_cost,
"type_id": seg_type}
}
route_features << feature
end
@path = { "type": "FeatureCollection",
"features": route_features
}

respond_to do |format|
format.json { render json: @path }
end
end

rails ajax tips

前不久在做一个rails项目时,要实现一个ajax刷新页面效果,rails能收到发来的请求,但是总是去渲染html页面,而不是渲染对应的js.erb文件,而这个controller里的action需要同时响应html和ajax请求。

那么rails是怎么和ajax结合的呢,首先要了解什么是SJR(Server-generated JavaScript Responses),这个可以看DHH大神的文章,翻译版:https://ruby-china.org/topics/16132

首先rails传统的ajax方案是给link或者form加一个:remote => true, 这样做会由jquery-ujs对链接进行劫持把普通请求变成ajax请求,其中很重要的一条就是增加一个datatype参数,然后在request请求中会带上Accept参数,rails会根据Accept进行响应分发。比如datatype为script,则响应js文件,datatype为json,则响应json文件。jquery-ujs默认的datatype为script。
这样做的话,那么下面的请求都会正常响应:

1
2
<%= link_to 'index', root_url %> //返回html
<%= link_to 'index', root_url, :remote => true %> //返回js

你还可以指定请求类型:

1
<%= link_to 'index', root_url, :remote => true, "data-type" => :json %> //返回json

如果自己写ajax请求的话要注意带上dataType,以保证rails正确响应你的请求:

1
2
3
4
5
6
$.ajax({
method: method,
url: action,
data: data,
dataType: 'script'
});

还有一种方案是在url中带上后缀,利用route将format传入action:

1
2
3
4
5
$.ajax({
method: method,
url: http://127.0.0.1:3000/index.js,
data: data,
});

action会根据format进行响应:

1
2
3
4
respond_to do |format|
format.html
format.js {} //返回js
end

参考:
http://tech.thereq.com/post/17243732577/rails-3-using-linkto-remote-true-with-jquery
http://roseweixel.github.io/blog/2015/07/05/integrating-ajax-and-rails-a-simple-todo-list-app/

正确配置geoserver标签(label)的姿势

label是地图上不可或缺的元素,geoserver的label是在geoserver的style文件中配置的,以下是我生产环境中的label配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<Rule>
<TextSymbolizer>
<!-- 配置显示label文字的属性,我这里是label -->
<Label>
<ogc:PropertyName>label</ogc:PropertyName>
</Label>
<Font>
<CssParameter name="font-size">12.0</CssParameter>
<CssParameter name="font-style">normal</CssParameter>
<CssParameter name="font-weight">bold</CssParameter>
</Font>
<Fill>
<CssParameter name="fill">#990099</CssParameter>
</Fill>
<!-- 取消默认的label重复显示 -->
<Geometry>
<ogc:Function name="centroid">
<ogc:PropertyName>the_geom</ogc:PropertyName>
</ogc:Function>
</Geometry>
<!-- label旋转角度 -->
<LabelPlacement>
<PointPlacement>
<Rotation>
45
</Rotation>
</PointPlacement>
</LabelPlacement>
</TextSymbolizer>
</Rule>

geoserver地图显示图标

geoserver地图上显示图标是常见的功能,比如一张室内地图上需要显示卫生间、电梯等图标。
wms地图
根据网上的资料整理出以下步骤:
1.上传需要显示的图标到geoserver的styles目录下,一般生产环境下是这个目录:
/var/lib/tomcat7/webapps/geoserver/data/styles
2.配置地图的sld样式文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Rule>
<Name></Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>type</ogc:PropertyName>
<ogc:Literal>toilet</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>

<PointSymbolizer>
<Graphic>
<ExternalGraphic>
<OnlineResource xlink:type="simple" xlink:href="http://wms.smart-museum.cn/geoserver/styles/wc.png" />
<Format>image/png</Format>
</ExternalGraphic>
<Size>20</Size>
</Graphic>
<VendorOption name="labelObstacle">true</VendorOption>
</PointSymbolizer>
</Rule>

因为我们上传图片到styles目录,所以xlink:href这个属性可以配置成绝对路径xlink:type="simple" xlink:href="wc.png",但是我的服务器上不知道什么原因就是不行,所以这里配置了绝对路径。以后查明了原因在更新。

解决hexo的jquery和fonts被墙

因为众所周知的原因,骄傲的中国人是不(wu)用(fa)访问ajax.googleapis.com和fonts.googleapis.com这两个网址的,所以jquery和google fonts会响应超时,严重影响我们的hexo博客的用户体验。解决方法是换成360提供的cdn,以hexo官方默认模版landscape为例:

1
2
3
4
5
6
打开
themes/landscape/layout/_partial/after-footer.ejs
找到
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
替换为
<script src="//ajax.useso.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>

1
2
3
4
5
6
打开
themes/landscape/layout/_partial/head.ejs
找到
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
替换为
<link href="//fonts.useso.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">

ref: http://libs.useso.com/

解决geoserver中文label乱码问题

将geoserver部署到ubuntu的时候,遇到label显示中文乱码的问题,一般这个问题都是因为ubuntu的jvm缺少中文字体造成的,记录下解决过程:

进入j2sdk目录,比如/usr/lib/jvm/java-7-openjdk-amd64/jre/lib,创建fallback目录:

sudo mkdir fonts/fallback

拷贝字体文件到fallback目录

cp xxx.ttf /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/fonts/fallback

安装fontconfig

sudo apt-get install fontconfig

rebuid fonts caches

fc-cache –fv

restart JVM

ionic-cheatsheet

在开发ionic过程中,会遇到各种报错,尤其是新添加了cordova的plugin后,很容易因为依赖问题build不通过,一般采取重装plugin和platform来解决:

1
2
3
4
5
6
sudo npm update -g cordova
sudo npm update -g ionic
rm -rf plugins/
rm -rf platforms/
ionic platform add ios
ionic run ios

安装plugin的时候,如果不想cordova plugin add xxx,而是一次安装所有的plugin

1
ionic state reset

ref: https://forum.ionicframework.com/t/how-to-install-all-my-codrova-plugins-listed-in-package-json/21328

打造顺手的开发环境

本文适用于MAC操作系统,程序员的电脑就像职业车手的座驾,应该把开发环境应该调教到最佳状态。以下基于我常用的技术栈react native、rails、git,整理出该环境下的“武功秘籍”:

Rails

第一式

招式:gem install时默认跳过ri、rdoc安装
步骤:打开 ~/.gemrc,加入gem: –no-ri –no-rdoc
心得:gem install默认会安装doc文件,十分浪费时间,我们有限的生命已经被GFW浪费够多的,这些小地方必须有寸土不让的精神。

NPM

第一式

招式:更换npm源
步骤:
三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在:
1.通过config命令

npm config set registry https://registry.npm.taobao.org 
npm info underscore (如果上面配置正确这个命令会有字符串response)

2.命令行指定

npm --registry https://registry.npm.taobao.org info underscore 

3.编辑 ~/.npmrc 加入下面内容

registry = https://registry.npm.taobao.org

Git

第一式

招式:增加git alias
步骤:

1
git config --global alias.alias command

For example, I use git status a lot, so a shorter alias would be nice:

1
git config --global alias.s status

This will add the following to your ~/.gitconfig file:

1
2
[alias]
s = status

Now if I type git s I get the same output as git status. Of course you can always open ~/.gitconfig in a text editor and add s = status manually under the [alias] section.

ref:http://oli.jp/2012/git-powerup/

SSH

第一式

招式: 配置ssh config快速登录服务器
步骤:
打开~/.ssh/config,加入以下内容:

1
2
3
4
5
6
7
8
9
Host hubei
HostName 192.168.40.11
User hbsb
Host yzsjzx
HostName 42.96.206.22
User wwwuser
Host camus
HostName 114.215.96.33
User wwwuser

以后可以这样登录服务器:ssh hubei

其它

第一式

招式:禁用DS_Store
步骤:
在命令行中执行:

defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true

删除系统中已经存在的DS_Store文件

sudo find / -name ".DS_Store" -depth -exec rm {} \;

然后记得重启finder

killall Finder

心得:
.DS_Store是Mac OS保存文件夹的自定义属性的隐藏文件,如文件的图标位置或背景色,相当于Windows的desktop.ini。这个文件经常会随着git提交到项目里,十分没必要。