aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: ef0b39e4905f4a32520d5eb47b8c52eb4779923e (plain)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# MMFWD
Forward calls and texts using ModemManager framework.

This is a daemon that forwards calls and text messages via email and
SIP(planned?). I made this python program to receive KYC messages whilst I'm
overseas. South Korea is a weird county where all KYC verifications are done via
personal mobile number. Without a mobile number, doing anything online is almost
impossible. The daemon can be run on a small and reliable device that is kept
somewhere safe.

- https://pygobject.gnome.org/getting_started.html
- https://code.nap.av.it.pt/mobility-networks/modemmanager/-/tree/1.18.12/examples/modem-watcher-python

![alt text](doc/img/mmfwd-email.webp)

![alt text](doc/img/mmfwd-email-sms.webp)

## Call answering machine (mmfwd-callam)
https://github.com/user-attachments/assets/b4782fbf-cf7d-4dba-8e81-26a8a6e084a0

https://github.com/user-attachments/assets/15a80630-4a53-4dc5-8954-4366e0f7c6d0

<video controls src="doc/img/sim7600-rickroll.post1.720p.mp4" title="sim7600-rickroll.post1.720p.mp4"></video>
<video controls src="doc/img/sim7600-incoming-call-2997.mp4" title="sim7600-incoming-call-2997.mp4"></video>

Usage:

```sh
mmfwd-callam <modem audio char path> <output prefix>
```

Making audio samples:

```sh
ffmpeg -i FILE -vn -ar 16000 -ac 1 -f s16le OUTFILE.pcm
```

or use Audacity:

- Go to `File` - `Export Audio`
  - Format: "Other uncompressed files"
  - Channel: Mono
  - Sample Rate: 16000 Hz
  - Header: RAW (header-less)
  - Encoding: Signed 16-bit PCM

Audacity overrides the extension to .raw. Change it to .pcm.

![alt text](doc/img/image.png)

The audio streaming is handled by the child process `mmfwd-callam` since the
audio serial port is synchronous(CTS/RTS). Common tools like `aplay` and
`arecord` do not support nonblocking IO.

[src/mmfwd-callam.cpp](src/mmfwd-callam.cpp):

```c
void init_params (void) {
	params.hello_sample_pat = "hello/*.pcm";
```

Place PCM files in `hello/*.pcm`. Then the main mmfwd Python module can spawn
the process.

[src/mmfwd/__init__.py](src/mmfwd/__init__.py):
```py
now = datetime.datetime.now(datetime.UTC)

n_from = call.get_number() or ""

dir = "rec/%02d-%02d" % (now.year, now.month)
filename = now.isoformat(timespec = 'milliseconds') + '_' + n_from
path = dir + '/' + filename

os.makedirs(dir, exist_ok = True)

exec = [ ud.instance.callam['exec'], "/dev/" + ud.audio_port, path ]
ud.instance.callam_proc = subprocess.Popen(exec)
# 5 minutes timeout
ud.instance.callam_timer = GLib.timeout_add_seconds(
	60 * 4,
	self.on_call_timeout,
	ud)
```

A pair of recorded audio files will be placed in
`rec/YYYY-MM/<ISOTIME in millis resolutiono>_<NUMBER>.<INOUT>` where

- NUMBER is the phone number of the calling party
- INOUT is "in" for the audio from the calling party and "out" for from mmfwd

To encode the recorded raw audio files:

```sh
ffmpeg -ar 16000 -ac 1 -f s16le -i PCM_FILE -c:a libopus OUTFILE.ogg
```

## Local playback
Config to enable. `1` for incoming audio only, `2` for outgoing audio only, `3`
for both. `0` to disable:

```yaml
mmfwd:
  instances:
    -
...
      call-am:
...
        playback: 1
...
```

### Enable ringtone (optional)
https://github.com/user-attachments/assets/209f5bdd-2e63-4373-81d2-5a47c403db82

<video controls src="doc/img/sim7600-playback.720p.30fps.mp4" title="sim7600-playback.720p.30fps.mp4"></video>

Make a simple ringtone:

```sh
# short bursts of alternating 250 and 500 Hz sine waves
truncate -s 0 bell.pcm
for (( i = 0; i < 6; i += 1 ))
do
  ffmpeg -loglevel error -f lavfi -i "sine=frequency=250:duration=0.1" -f s16le -ar 16000 -ac 1 - >> bell.pcm
  ffmpeg -loglevel error -f lavfi -i "sine=frequency=500:duration=0.2" -f s16le -ar 16000 -ac 1 - >> bell.pcm
done

# encode it to opus
ffmpeg -loglevel error -f s16le -ar 16000 -ac 1 -i bell.pcm -c:a libopus ringtone.ogg
```

Config to enable ringtone:

```yaml
        ringtone-exec:
          - ffplay
          - -loglevel
          - error
          - -autoexit
          - -nodisp
          - ringtone.ogg
...
```

## MM Patches
- https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1293
- https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/996

## Another idea (070 number)
Major telcos in South Korea(KT, SKT, LG U+) offer VoIP services. After
subscribing to such services, the SIP credentials can be extracted from the
device. AFAIK, the telcos' SIP servers don't do whitelist connections so the
credentials can be used pretty much from anywhere with any SIP+VoIP client
implementations.

Sources:

- https://blog.naver.com/rehearsal/80099885977
- https://www.clien.net/service/board/use/1219343
- https://koreapyj.dcmys.kr/152

ModemManager and LTE modems such as SIM7600 are usually optimised for mobile
date network connectivity on Linux world, not for voice calls. You might as well
get a 070 number(the standard VoIP prefix in Korea) and redirect the calls and
messages to the SIM number to the VoIP number to get high quality audio straight
from the telcos' IP core network.

- Pro: Stable audio stream
- Con: Adding another point of failure to the system