Skip to content

Commit

Permalink
Merge pull request #39 from owulveryck/websocket
Browse files Browse the repository at this point in the history
Streaming v2
  • Loading branch information
owulveryck authored Jun 26, 2023
2 parents 33be954 + ed0a21d commit 6df9bff
Show file tree
Hide file tree
Showing 55 changed files with 815 additions and 4,360 deletions.
Binary file removed .DS_Store
Binary file not shown.
9 changes: 0 additions & 9 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ jobs:
with:
go-version: 1.20.4

- name: Install Protoc
uses: arduino/setup-protoc@v1

- name: Install the protoc-gen-gofast binary
run: go get github.com/gogo/protobuf/protoc-gen-gofast && go install github.com/gogo/protobuf/protoc-gen-gofast

- name: Generate certs
run: go generate ./...

- name: Build
run: go build -v ./...

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ internal/client/memprofileImageH5.out
internal/client/memprofileImageH6.out
server/htdocs/assets/toEpub.wasm
client/htdocs/assets/toEpub.wasm
goMarkableStream
testServer.arm
19 changes: 2 additions & 17 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,18 @@ before:
# You may remove this if you don't use go modules.
- go mod download
# you may remove this if you don't need go generate
- go get github.com/gogo/protobuf/protoc-gen-gofast
- go install github.com/gogo/protobuf/protoc-gen-gofast
- go generate ./...
builds:
- env:
- CGO_ENABLED=0
id: "Server"
main: ./server/.
binary: goMarkableStreamServer.arm
main: .
binary: goMarkableStream
goos:
- linux
goarch:
- arm
goarm:
- 7
- env:
- CGO_ENABLED=0
id: "Client"
main: ./client/.
binary: goMarkableClient
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
archives:
- name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
wrap_in_directory: true
Expand Down
200 changes: 55 additions & 145 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,183 +1,93 @@
[![Go](https://github.com/owulveryck/goMarkableStream/actions/workflows/go.yml/badge.svg)](https://github.com/owulveryck/goMarkableStream/actions/workflows/go.yml)

# goMarkableStream
## Overview

I use this project to stream my remarkable 2 (firmware 2.5+) on my laptop using the local wifi.
This project does not need any hack installed on the remarkable (only the server which should not void the warranty).
This project does not rely on any exterrnal dependencies and should run on Linux, Windows and. MacOS.

[video that shows some features](https://www.youtube.com/watch?v=PzlQ2hEIdCc)

And [another one](https://youtu.be/0PCyUn_-x6Y) that shows the experimental colorize featur

## Quick start

You need ssh access to your remarkable

Download two files from the [release page](https://github.com/owulveryck/goMarkableStream/releases):

- the server "`Linux/Armv7`" for your remarkable
- the client for your laptop according to the couple `OS/arch`

or build it yourself if you have the go toolchain installed on your machine.

### The server

Copy the server on the remarkable and start it.

```shell
scp goMarkableStreamServer.arm remarkable:
ssh remarkable 'chmod +x goMarkableStreamServer.arm ; ./goMarkableStreamServer.arm'
```

Note: The processus is fault tolerant and should resume automatically on sleep/wakup or network failure; therefore, you can, normally, launch the processus in background (with `nohup`)


### The client

- Start the client: `RK_SERVER_ADDR=ip.of.remarkable:2000 ./goMarkableClient`

- Point your browser to [`http://localhost:8080/`](http://localhost:8080/)

The client exposes those endpoints:

- `/screenshot` takes a screenshot in png
- `/orientation?orientation=[landscape|portrait]` to change the orientation
- `/conf` ugly and incomplete configuration panel
- `/gob` to get a gob encoded picture (for development purpose)
- `/raw` to get a raw picture (a gray bitmap image)

_Note_: click on the video to take a screenshot. The screenshot is a png file with transparent background.

### Configuration

It is possible to tweak the configuration via environment variables:

#### Server

| Env var | Default | Descri[ption
|---------------------|-----------|---------------
| RK_SERVER_BIND_ADDR | :2000 | the TCP listen address

#### Client

| Env var | Default | Descri[ption
|---------------------------|-----------------|---------------
| RK_CLIENT_BIND_ADDR | :8080 | the TCP listen address
| RK_SERVER_ADDR | remarkabke:2000 | the address of the remarkable
| RK_CLIENT_AUTOROTATE | true | activate autorotate (see below)
| RK_CLIENT_PAPER_TEXTURE | null | a path to a texture
| RK_CLIENT_COLORIZE | true | colorize function
| RK_CLIENT_HIGHLIGHT | false | highlight function (cannot work with colorize)
The goMarkableStream is a lightweight and user-friendly application designed specifically for the reMarkable tablet.
Its primary goal is to enable users to stream their reMarkable tablet screen to a web browser without the need for any hacks or modifications that could void the warranty.

## Features

### Auto-rotate

The client tries to locate the location of the top level switch on the picture (the round one) and rotate the picture accordingly.
This experimental behavior can be disabled by env variables in the client.

Note: the browser does not like the switch of the rotation; the reload of the page solves the problem

### Texture

There is an experimental texture feature that reads a texture file and use is as a background in the output. The texture does
not apply to the screenshot.
The texture must have this format:

```shell
> identify textures/oldpaper.png
textures/oldpaper.png PNG 1872x1404 1872x1404+0+0 8-bit Gray 256c 886691B 0.010u 0:00.001
```
- No hacks or warranty voiding: The tool operates within the boundaries of the reMarkable tablet's intended functionality and does not require any unauthorized modifications.
- No subscription required: Unlike other screen streaming solutions, this tool does not impose any subscription fees or recurring charges. It is completely free to use.
- No client-side installation: Users can access the screen streaming feature directly through their web browser without the need to install any additional software or plugins.
- Color support

Example:
## Quick Start

```shell
RK_CLIENT_PAPER_TEXTURE=./textures/oldpaper.png goMarkableClient
```text
ssh root#remarkable
curl -O https://github.com/owulveryck/goMarkableStream/releases/download/v0.8.0/goMarkableStream
chmod+x goMarkableStream
./goMarkableStream
```

![exemple](docs/textures.png)
then go to [https://remarkable:2001](https://remarkable:2001) and login with `admin`/`password` (can be changed through environment variables)

_note_: replace _remarkable_ by the IP address if needed.

### Colorize
## Technical Details

This option can be activated with the `RK_CLIENT_COLORIZE=true` env variable. This tries to set the highlighter and colors in yellow in the video stream.
### Data Retrieval from reMarkable Memory

**Caution** This is CPU intensive.
The reMarkable Screen Streaming Tool leverages a combination of techniques to capture the screen data from the reMarkable tablet's memory.
It utilizes low-level access provided by the device's operating system to retrieve the necessary data.
This approach ensures that the tool does not require any unauthorized modifications to the reMarkable tablet.

![exemple](docs/colorize.png)
### Data Transmission via WebSocket

### Screenshot
Once the screen data is obtained from the reMarkable tablet's memory, the tool serves it to clients via a WebSocket connection.
A WebSocket is a communication protocol that provides full-duplex communication channels over a single TCP connection, making it ideal for real-time data streaming.
The WebSocket connection ensures that the screen data is transmitted efficiently and promptly to connected clients.

The server is exposing a screenshot endpoint. You can grab a screenshot by clicking on the video stream, or by using tools such as curl:
### Client-Side Rendering with HTML Canvas

ex:
```shell
❯ curl -o /tmp/screenshot.png http://localhost:8080/screenshot
❯ file /tmp/screenshot.png
/tmp/screenshot.png: PNG image data, 1404 x 1872, 8-bit/color RGBA, non-interlaced
```

### Raw picture

the `/raw` endpoind exposes the raw picture without any treatment. It is possible to pipe the result into a thrid party tool such as imageMagick for example.

This generates a pdf from the screen
```shell
curl http://localhost:8080/raw | convert -depth 8 -size 1404x1872+0 gray:- shot.pdf
```
On the client side, the reMarkable Screen Streaming Tool fetches the transmitted screen data and renders it using an HTML canvas element.
The HTML canvas provides a powerful and flexible platform for displaying graphics and images on web pages.
By leveraging the capabilities of the HTML canvas, the tool ensures a performant and lossless streaming experience for users.

## How it works?
## Getting Started

### Full explanation
To use the reMarkable Screen Streaming Tool, follow these steps:

I wrote a [blog post](https://blog.owulveryck.info/2021/03/30/streaming-the-remarkable-2.html) that explains all the wiring.
Otherwise a summary is written here.
### Installation

### The server loop
1. Ensure that you have a reMarkable tablet and a computer or device with an ssh client.
2. Get a compiled version from the release or compile it yourself
3. copy the utility on the tablet

- The server gets the address of the framebuffer in the memory space of the `xochitl`
- The server launches a "ticketing system" to avoid congestion. The ticketing system is a channel that gets an event every 200ms.
- Then it exposes a gRPC function (with TLS and mutual authentication).
- The gRPC function waits for a "ticket" on the channel, and then grabs the data from the framebuffer.
- It packs the data into an `image` message encoded in protobuf and sends it to the consumer
### Run

### The client loop
1. launch the utility by conencting via ssh and launch `./goMarkableStream &`
2. go to https://IP-OF-REMARKABLE:2001 (you need to accept the self-signed certificate)

- The client creates an `MJPEG` stream and serves it over HTTP on the provided address
- The client dial server and sends its certificate, and add the compression header.
- Then it triggers a goroutine to get the `image` in a for loop.
- The image is then encoded into JPEG format and added to the MJPEG stream.
The application is configured via environment variables:

```text
This application is configured via the environment. The following environment
variables can be used:
## Security
KEY TYPE DEFAULT REQUIRED DESCRIPTION
RK_SERVER_BIND_ADDR String :2001 true
RK_SERVER_DEV True or False false
RK_SERVER_USERNAME String admin
RK_SERVER_PASSWORD String password
RK_HTTPS True or False true
```

The communication is using TLS. The client and the server owns an embedded certificate chain (with the CA). There are performing mutual authentication.
A new certificate chain is generated per build. Therefore, if you want restrict the access to your server to your client only, you must rebuild the tool yourself.
### Compilation

### Manual build
`GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 go build .`

_Note_: you need go > 1.16beta to build the tool because of the embedding mechanism for the certificate.
## Contributing

To build the tool manually, the easiest way is to use `goreleaser`:
I welcome contributions from the community to improve and enhance the reMarkable Screen Streaming Tool. If you have any ideas, bug reports, or feature requests, please submit them through the GitHub repository's issue tracker.

```shell
goreleaser --snapshot --skip-publish --rm-dist
```
## License

To build the services manually:
The reMarkable Screen Streaming Tool is released under the [MIT License](https://opensource.org/licenses/MIT) . Feel free to modify, distribute, and use the tool in accordance with the terms of the license.

```shell
go generate ./... # This generates the certificates
cd server && GOOS=linux GOARCH=arm GOARM=7 go build -o goStreamServer.arm
cd client && go build -o goStreamClient
```

# Tipping
## Tipping

If you plan to buy a reMarkable 2, you can use my [referal program link](https://remarkable.com/referral/PY5B-PH8U). It will provide a discount for you and also for me.

## Acknowledgement

All the people in the reStream projet and specially
[@ddvk](https://github.com/ddvk) and [@raisjn](https://github.com/raisjn)
31 changes: 31 additions & 0 deletions auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"fmt"
"net/http"
)

// BasicAuthMiddleware is a middleware function that adds basic authentication to a handler
func BasicAuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check if the request is authenticated
user, pass, ok := r.BasicAuth()
if !ok || !checkCredentials(user, pass) {
// Authentication failed, send a 401 Unauthorized response
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "Unauthorized")
return
}

// Authentication succeeded, call the next handler
next.ServeHTTP(w, r)
})
}

// checkCredentials is a dummy function to validate the username and password
func checkCredentials(username, password string) bool {
// Add your custom logic here to validate the credentials against your storage (e.g., database, file)
// This is a basic example, so we're using hard-coded credentials for demonstration purposes.
return username == c.Username && password == c.Password
}
21 changes: 21 additions & 0 deletions cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUBAVfurBI2ze6o814cYTubdIgV/gwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA2MjMwNzM1MzlaFw0zMzA2
MjAwNzM1MzlaMEUxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQD2CZ/+7qzKTRk02kaPT+U5yu3oTuggkkwkcUUE5gIk
CbhvsLQ4aIx2QHmol1rkfO1LgA7mfyVhO5D4QqwANBieEdO6x+B2KUCo5NQTblBY
17e+OpN6w4s2eNSoB1/BaO8zICqj3GaIcyKCIrXB5zxKXjRbAgiZ7nEsN3R1HKC9
aL2l/j++X6kd4ET2LSsu5JHqYlYMipZ2TVK/FieBEoKdtb0Fm1es8P3j36uByY2v
p0wvh4a6eGxmxFCrFDSUhk8mLteT+1doUrGj4LdmCw8MKdVmK+BbZSntdNP6/2Rd
gB0MleQdLzB/YjgrXo4Au47YXAI8FNXkWADpJqWD/mnxAgMBAAGjUzBRMB0GA1Ud
DgQWBBSMCi3QGHRzKz7CEsD2O0zX+LgnTzAfBgNVHSMEGDAWgBSMCi3QGHRzKz7C
EsD2O0zX+LgnTzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA4
LYSX4UhGfHkCldTV0Ug0Fn6rDyBMOfEIYL1WJVvBjEB9CP8aQ8ooRuwzKUaQihbq
KP13r27/uTQ9GrJ9+/Oroqv2iJJPfrSiZsPeKoymjaAT2cvi3qlMYtPVMjIJpSdE
WapJ5VOG6rnCWJfuF2KWR7cxmJ2DOlZu/unOzr5nHfLRxCZaFJhubrCgMlZ8MkqO
aE532ai+E9QRlDs9PS9D9Un7iUw3auvytDtlcxh0UkVHlELF5miJMwNFyMtI7xgm
RSqRM43aEgC4sos413lMNnXqB7bbJsoKOqGTo/j4d+hfPRXi1jntccdtma6NyX7T
vuMr9+DhDxVR/ZD+oci0
-----END CERTIFICATE-----
26 changes: 0 additions & 26 deletions certs/cmd/main.go

This file was deleted.

Loading

0 comments on commit 6df9bff

Please sign in to comment.