Skip to content

Commit

Permalink
docs: update README
Browse files Browse the repository at this point in the history
  • Loading branch information
rick-jennings committed Oct 10, 2024
1 parent bf3afc5 commit 9b30676
Showing 1 changed file with 9 additions and 255 deletions.
264 changes: 9 additions & 255 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ About
-----
Phable is a simple, modern Python toolkit for basic client connectivity to a [Project Haystack](https://project-haystack.org/) server.

We aimed to make code within Phable's client.py and kinds.py modules self-documenting by using type hints and docstrings and carefully selecting what is publicly exposed. In the future we plan to improve docs and release a stable version 1.0.0 for Phable.

Installation
------------
Phable requires Python version 3.11 or higher and generally has no required software dependencies. Download Phable from PyPI using:
Expand All @@ -14,266 +12,22 @@ $ pip install phable

Phable uses the `zoneinfo` module for IANA time zone support, which by default uses the system's time zone data if available. If no system time zone data is available, then Phable requires the `tzdata` package available on PyPI to be installed.

Phable has an optional `pandas` package dependency that is required for `phable.kinds.Grid.to_pandas()`. Download Phable with `pandas` from PyPI using:
Phable has an optional `pandas` package dependency that is required for `phable.Grid.to_pandas()` and `phable.Grid.to_pandas_all()`. Download Phable with `pandas` from PyPI using:

```console
$ pip install "phable[pandas]"
```

Note: Most of the below examples require the optional `pandas` package dependency.

Example: A Custom SSL Context & Haystack's About op
---------------------------------------------------
```python
from datetime import date

from phable.client import Client
import ssl

# define these settings specific to your use case
uri = "https://host"
username = "<username>"
password = "<password>"
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

with Client(uri, username, password, ssl_context) as ph:
about = ph.about()

print("Here is information about the Haystack server:\n")
print(about)
```

Example: Haystack's Read & HisRead ops
--------------------------------------
```python
from datetime import date

from phable.client import Client

# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "<username>"
password = "<password>"

with Client(uri, username, password) as ph:
# read history data on main electric meter power points
pts = ph.read("point and power and equipRef->siteMeter")
his_df = ph.his_read(pts, date.today()).to_pandas()

print("Here is the Pandas DataFrame showing point history data:\n")
print(his_df)
print()
print(f"Here are the DataFrame's attributes:\n{his_df.attrs}")

# Notes:
# 1. These attributes contain info from the point grid
# 2. Later we may add some funcs to help parse the DataFrame attributes
# 3. History Grids converted to Pandas DataFrames show point Ref display names
# for their column names
```

Example: Haystack's Read & HisRead ops using IDs and DateRange
--------------------------------------------------------------
```python
from datetime import date, timedelta

from phable.client import Client
from phable.kinds import DateRange, Ref

# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "<username>"
password = "<password>"
Similarly, Phable has an optional `polars` package dependency that is required for `phable.Grid.to_polars()` and `phable.Grid.to_polars_all()`. Download Phable with `polars` from PyPI using:

# update the ids for your server
id1 = Ref("p:demo:r:2caffc8e-aa932383")
id2 = Ref("p:demo:r:2caffc8e-1768df4f")

end = date.today()
start = end - timedelta(days=2)
range = DateRange(start, end)

with Client(uri, username, password) as ph:
pts_df = ph.read_by_ids([id1, id2]).to_pandas()
his_df = ph.his_read_by_ids([id1, id2], range).to_pandas()

print("Here is the Pandas DataFrame showing point data:\n")
print(pts_df)
print()
print("Here is the Pandas DataFrame showing point history data:\n")
print(his_df)
print()
print(f"Here are attributes on the History DataFrame:\n{his_df.attrs}")

# Notes:
# 1. There are fewer attributes preserved when using Client.his_read_by_ids()
# compared to Client.read_by_ids()
# 2. History Grids converted to Pandas DataFrames show point Ref display names
# for their column names
```

Example: Async Usage without Context Manager
--------------------------------------------
```python
import asyncio

from phable.client import Client


async def main() -> None:
# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "<username>"
password = "<password>"

ph = Client(uri, username, password)

ph.open()
power_pt_read = asyncio.to_thread(ph.read, "power and point")
energy_pt_read = asyncio.to_thread(ph.read, "energy and point")
power_pt_read, energy_pt_read = await asyncio.gather(power_pt_read, energy_pt_read)
ph.close()

# convert Grids to Pandas DataFrames and print the results
power_pt_read = power_pt_read.to_pandas()
energy_pt_read = energy_pt_read.to_pandas()

print(power_pt_read)
print(energy_pt_read)


if __name__ == "__main__":
asyncio.run(main())
```

Example: History Write to a Single Point
----------------------------------------
```python
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

from phable.client import Client
from phable.kinds import Number, Ref

# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "su"
password = "su"


ts_now = datetime.now(ZoneInfo("America/New_York"))
data_rows = [
{
"ts": ts_now - timedelta(seconds=30),
"val": Number(1_000.0, "kW"),
},
{
"ts": ts_now,
"val": Number(2_000.0, "kW"),
},
]

with Client(uri, username, password) as ph:
ph.his_write_by_ids(Ref("2d6a2714-0d0a79fb"), data_rows)
```

Example: History Write to Multiple Points
-----------------------------------------
```python
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

from phable.client import Client
from phable.kinds import Number, Ref

# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "su"
password = "su"


ts_now = datetime.now(ZoneInfo("America/New_York"))
data_rows = [
{
"ts": ts_now - timedelta(seconds=30),
"v0": Number(3_000.0, "kW"),
},
{
"ts": ts_now,
"v1": Number(4_000.0, "kW"),
},
]

# Ref at index 0 of ids corresponds to data values in col v0
# Ref at index 1 of ids corresponds to data values in col v1
ids = [Ref("2d6a2714-0d0a79fb"), Ref("2d6a2714-503317c5")]

with Client(uri, username, password) as ph:
ph.his_write_by_ids(ids, data_rows)
```

Example: SkySpark's Eval Op
---------------------------
```python
from phable.client import Client

# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "su"
password = "su"


with Client(uri, username, password) as ph:
his_df = ph.eval(
"""read(power and point and equipRef->siteMeter)
.hisRead(lastMonth)"""
).to_pandas()

print("Here is the Pandas DataFrame showing point history data:\n")
print(his_df)
print()
print(f"Here are the DataFrame's attributes:\n{his_df.attrs}")
```


Example: SkySpark's Commit Op
-----------------------------
```python
from phable.client import Client, CommitFlag
from phable.kinds import Grid, Marker

# define these settings specific to your use case
uri = "http://localhost:8080/api/demo"
username = "su"
password = "su"

# create the client object and open the connection
ph = Client(uri, username, password)
ph.open()

# create a new rec on SkySpark
rec = [{"dis": "TestRec", "testing": Marker(), "pytest": Marker()}]
response1: Grid = ph.commit(rec, CommitFlag.ADD)

# update the newly created rec
# Note: the id column and current mod timestamp must be included
rec = [
{"id": response1.rows[0]["id"], "mod": response1.rows[0]["mod"], "foo": "new tag"}
]
response2: Grid = ph.commit(rec, CommitFlag.UPDATE)

# delete the newly created and updated rec
# Note: the rec should have only an id and mod column
rec = [{"id": response2.rows[0]["id"], "mod": response2.rows[0]["mod"]}]
response: Grid = ph.commit(rec, CommitFlag.REMOVE)

# close the session with the Haystack server (SkySpark)
ph.close()
```console
$ pip install "phable[polars]"
```


Breaking Changes
----------------
The early focus of this project is to find the best practices for using modern Python with a Haystack server. This may lead to breaking changes in newer Phable versions. We plan to release a stable version 1.0.0 of Phable sometime in 2024 (TBD).
The early focus of this project is to find the best practices for using modern Python with a Haystack server. This may lead to breaking changes in newer Phable versions. After there has been sufficient experience with Phable, we plan to release a stable version 1.0.0.

Learn More
----------
Phable's official website located [here](https://phable.dev/) has additional documentation and examples for Phable's API.

0 comments on commit 9b30676

Please sign in to comment.