V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
guxin0123
V2EX  ›  程序员

BPC 电波授时信号 Python 转 js 实现一半 求助

  •  
  •   guxin0123 · 2017-03-14 15:39:06 +08:00 · 2564 次点击
    这是一个创建于 2572 天前的主题,其中的信息可能已经有所发展或是发生改变。

    来源 http://www.hackrf.net

    有个六局电波的西铁城,由于地理位置偏僻收不到波

    网上看到了这个 《 BPC 电波授时信号的“零成本”伪造》 用 Python+耳机发射授时信号

    上网查了查 在苹果商店发现一个 app 售价 12 但是没有苹果手机

    觉得要是把他的代码改到 js 里面就可以在浏览器里面运行对时就非常方便了

    目前只完成了时间转 base4 部分 但是 js 音频发声转换部分没有思路 对音频和波形没有研究过

    看了两个库 timbre.js 和 lame.js 不知是否可行

    python 代码

    # -*- coding: utf-8 -*-
    """
    Created on Tue Jan 19 15:26:45 2016
    
    @author: zhengbowang
    """
    import pyaudio
    import struct
    import datetime
    import math
    
    def dropandfill(l,s):return '0'*(l - len(s[2:])) + s[2:]#用 0 补位
    def time2code(date_time, dt = datetime.timedelta(0)):
    
    #将时间转换成 BPC 编码。
    
        date_time -= dt
        date = [date_time.day, date_time.month, date_time.year]
        timet = [date_time.hour,date_time.minute,date_time.weekday()+1]
        date[2] = date[2]%100#year
        timet[0] = timet[0]%12#am.pm
        p1 = dropandfill(2,bin(date_time.second/20))#seconds
        p2 = '00'#reserved
        sec1 = (p1+p2)+''.join(map(dropandfill,[4,6,4],map(bin,timet)))
        p31 = str(int(date_time.hour>=12))
        p32 = str((sec1.count('1'))%2)
        p3 = p31 + p32
        sec2 = ''.join(map(dropandfill,[6,4,6],map(bin,date)))
        p41 = str(int(date_time.year%1000>100))
        p42 = str(((sec2.count('1'))%2))
        p4 = p41 + p42
        code2 = sec1 + p3 +sec2 + p4
        bin2four = {'00':'1','01':'2','10':'3','11':'4'}#to base4
        return '0'+''.join([bin2four[code2[2*i:2*i+2]] for i in range(len(code2)/2)])
    
    dt = datetime.timedelta(hours = 1)#fake time shift
    samp_rate = 68500
    freq = 6850 * 2 #in Hertz
    ttime =20 #in Sec
    SAMPLE_LEN = samp_rate * ttime # 20 seconds of cosine
    value = ampl = 32725
    div = samp_rate/freq/2
    data = 32725
    # 打开声音输出流
    p = pyaudio.PyAudio()
    stream = p.open(format = 8,
                    channels = 1,
                    rate = samp_rate,
                    output = True)
    
    while True:
        date_time = datetime.datetime.now()+dt
        print date_time
        sec = (date_time.second+1)%20
        code_str = time2code(date_time)
        start = sec * samp_rate
        for i in xrange((start), SAMPLE_LEN):
            #if i % div == 0:value = -value#carrier generate
            value = ampl * int(math.cos(math.pi / float(div) * float(i)))
            pulse = (i - sec * samp_rate)/(samp_rate / 10)
            packed_value = struct.pack('h', int(pulse >= int(code_str[sec]))*value)
            stream.write(packed_value)
            if i % samp_rate == 0 and i != start: 
                sec = sec + 1
    

    转到一半的 js 代码

    function time2code(date_time) {
                var date = [date_time.getDate(), date_time.getMonth() + 1, date_time.getFullYear()];
                var timet = [date_time.getHours(), date_time.getMinutes(), date_time.getUTCDay()];
                date[2] = date[2] % 100; //year
                timet[0] = timet[0] % 12; //am,pm
                var p1 = dropandfill(2, parseInt(date_time.getSeconds() / 20).toString(2)); //seconds
                var p2 = '00'; //reserved
                var sec1 = (p1 + p2) + '' + join(map(dropandfill, [4, 6, 4], map(bin, timet)))
                var p31 = Number(date_time.getHours() >= 12).toString();
                var re = new RegExp("1", "g");
                var p32 = str((sec1.match(re).length) % 2)
                var p3 = p31 + p32;
    
                var sec2 = '' + join(map(dropandfill, [6, 4, 6], map(bin, date)));
                var p41 = str(Number(date_time.getFullYear() % 1000 > 100))
                var p42 = str(((sec2.match(re).length) % 2))
                var p4 = p41 + p42
                var code2 = sec1 + p3 + sec2 + p4
                var bin2four = { '00': '1', '01': '2', '10': '3', '11': '4' } //to base4
                var ret = [];
                ret.push('0')
                for (var i = 0; i < code2.length / 2; i++) {
                    ret.push(bin2four[code2.substring(i * 2, i * 2 + 2)]);
                }
                return join(ret);
            }
    
            //用 0 补位
            function dropandfill(size, num) {
                var s = "000000000" + num;
                return s.substr(s.length - size);
            }
    
            function map(a, b) {
                if (arguments.length == 2) {
                    for (var i = 0; i < arguments[1].length; i++) {
                        arguments[1][i] = arguments[0](arguments[1][i]);
                    }
                    return arguments[1];
                }
                if (arguments.length == 3) {
                    for (var i = 0; i < arguments[1].length; i++) {
                        arguments[1][i] = arguments[0](arguments[1][i], arguments[2][i]);
                    }
                    return arguments[1];
                }
    
            }
            function bin(e) {
                return e.toString(2);
            }
            function join(e) {
                var ret = "";
                for (var i = 0; i < e.length; i++) {
                    ret += e[i];
                }
                return ret;
            }
            function str(e) {
                return e.toString();
            }
    
    2 条回复    2017-08-08 19:27:05 +08:00
    GPU
        1
    GPU  
       2017-08-08 18:39:21 +08:00 via iPhone
    好像还有一个 68.5kHz 的 5 倍频要处理
    guxin0123
        2
    guxin0123  
    OP
       2017-08-08 19:27:05 +08:00
    发现一个别人做好的了

    https://shogo82148.github.io/web-jjy/
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2563 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 15:41 · PVG 23:41 · LAX 08:41 · JFK 11:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.