Skip to content
This repository was archived by the owner on Feb 7, 2025. It is now read-only.

Commit 46089c8

Browse files
authored
Merge pull request #19 from komp15/PWRAPI-116-offset-last-update-time-for-europe-warsaw-timezone
Added iParking support and automatic switching between iParking and SKD
2 parents 0f6b597 + 8f36dd3 commit 46089c8

File tree

13 files changed

+380
-16
lines changed

13 files changed

+380
-16
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package dev.wms.pwrapi.dao.parking;
2+
3+
import java.io.IOException;
4+
import java.time.LocalDateTime;
5+
import java.time.format.DateTimeFormatter;
6+
import java.util.*;
7+
8+
import com.fasterxml.jackson.databind.DeserializationFeature;
9+
import com.fasterxml.jackson.databind.ObjectMapper;
10+
11+
import dev.wms.pwrapi.dto.parking.ParkingWithHistory;
12+
import dev.wms.pwrapi.dto.parking.deserialization.ParkingWithHistoryArrayElement;
13+
import dev.wms.pwrapi.dto.parking.deserialization.ParkingWithHistoryResponse;
14+
import dev.wms.pwrapi.utils.parking.ParkingGeneralUtils;
15+
import org.springframework.context.annotation.Primary;
16+
import org.springframework.stereotype.Repository;
17+
18+
import dev.wms.pwrapi.dto.parking.deserialization.ParkingArrayElement;
19+
import dev.wms.pwrapi.dto.parking.deserialization.ParkingResponse;
20+
import dev.wms.pwrapi.dto.parking.Parking;
21+
import dev.wms.pwrapi.utils.parking.exceptions.WrongResponseCode;
22+
import okhttp3.MediaType;
23+
import okhttp3.OkHttpClient;
24+
import okhttp3.Request;
25+
import okhttp3.RequestBody;
26+
import okhttp3.Response;
27+
28+
@Repository
29+
public class IParkingDAO implements ParkingDAO {
30+
31+
32+
@Override
33+
public ArrayList<Parking> getProcessedParkingInfo() throws IOException {
34+
35+
ArrayList<Parking> result = new ArrayList<Parking>();
36+
37+
OkHttpClient client = new OkHttpClient().newBuilder()
38+
.build();
39+
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8");
40+
RequestBody body = RequestBody.create(mediaType, "o=get_parks&ts=1652019293233");
41+
Request request = new Request.Builder()
42+
.url("https://iparking.pwr.edu.pl/modules/iparking/scripts/ipk_operations.php")
43+
.method("POST", body)
44+
.addHeader("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Google Chrome\";v=\"100\"")
45+
.addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
46+
.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
47+
.addHeader("X-Requested-With", "XMLHttpRequest")
48+
.addHeader("sec-ch-ua-mobile", "?0")
49+
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36")
50+
.addHeader("sec-ch-ua-platform", "\"Windows\"")
51+
.addHeader("Sec-Fetch-Site", "same-origin")
52+
.addHeader("Sec-Fetch-Mode", "cors")
53+
.addHeader("Sec-Fetch-Dest", "empty")
54+
.addHeader("Referer", "https://iparking.pwr.edu.pl/")
55+
.addHeader("Origin", "https://iparking.pwr.edu.pl")
56+
.build();
57+
Response response = client.newCall(request).execute();
58+
59+
ParkingResponse deserializedResponse = new ObjectMapper().readValue(response.body().string(), ParkingResponse.class);
60+
61+
if (deserializedResponse.getSuccess() != 0) throw new WrongResponseCode();
62+
63+
DateTimeFormatter parkingFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
64+
for (ParkingArrayElement parking : deserializedResponse.getPlaces()) {
65+
66+
Parking toAdd = new Parking().builder()
67+
.name(ParkingGeneralUtils.determineParking(parking.getParking_id()))
68+
.lastUpdate(LocalDateTime.parse(parking.getCzas_pomiaru(), parkingFormatter).toString())
69+
.leftPlaces(Integer.valueOf(parking.getLiczba_miejsc()))
70+
.trend(Integer.valueOf(parking.getTrend()))
71+
.build();
72+
73+
result.add(toAdd);
74+
}
75+
76+
77+
return result;
78+
}
79+
80+
@Override
81+
public List<ParkingWithHistory> getRawParkingData() throws IOException {
82+
83+
OkHttpClient client = new OkHttpClient().newBuilder()
84+
.build();
85+
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8");
86+
RequestBody body = RequestBody.create(mediaType, "o=get_parks&ts=1652019293233");
87+
Request request = new Request.Builder()
88+
.url("https://iparking.pwr.edu.pl/modules/iparking/scripts/ipk_operations.php")
89+
.method("POST", body)
90+
.addHeader("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Google Chrome\";v=\"100\"")
91+
.addHeader("Accept", "application/json, text/javascript, */*; q=0.01")
92+
.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
93+
.addHeader("X-Requested-With", "XMLHttpRequest")
94+
.addHeader("sec-ch-ua-mobile", "?0")
95+
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36")
96+
.addHeader("sec-ch-ua-platform", "\"Windows\"")
97+
.addHeader("Sec-Fetch-Site", "same-origin")
98+
.addHeader("Sec-Fetch-Mode", "cors")
99+
.addHeader("Sec-Fetch-Dest", "empty")
100+
.addHeader("Referer", "https://iparking.pwr.edu.pl/")
101+
.addHeader("Origin", "https://iparking.pwr.edu.pl")
102+
// .addHeader("Cookie", "PHPSESSID=sgn0fqbs1vg9bjotuum1aha957")
103+
.build();
104+
Response response = client.newCall(request).execute();
105+
String stringResponse = response.body().string();
106+
System.out.println(stringResponse);
107+
ObjectMapper mapper = new ObjectMapper();
108+
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
109+
ParkingWithHistoryResponse parkingWithHistoryResponses = mapper.readValue(stringResponse, ParkingWithHistoryResponse.class);
110+
List<ParkingWithHistory> result = new ArrayList<>();
111+
DateTimeFormatter parkingFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
112+
for(ParkingWithHistoryArrayElement parking : parkingWithHistoryResponses.getPlaces()){
113+
114+
ParkingWithHistory toAdd = ParkingWithHistory.builder()
115+
.name(ParkingGeneralUtils.determineParking(parking.getParking_id()))
116+
.lastUpdate(LocalDateTime.parse(parking.getCzas_pomiaru(), parkingFormatter).toString())
117+
.history(parseHistory(parking.getChart().getX(), parking.getChart().getData()).toString().replace("{","").replace("}", ""))
118+
.build();
119+
result.add(toAdd);
120+
}
121+
return result;
122+
}
123+
124+
private Map<String, String> parseHistory(List<String> hours, List<String> state){
125+
Map<String, String> states = new TreeMap<>();
126+
for(int i = 0; i < hours.size(); i++){
127+
states.put(hours.get(i), state.get(i));
128+
}
129+
return states;
130+
}
131+
132+
133+
}

src/main/java/dev/wms/pwrapi/dao/parking/ParkingDAOImpl.java renamed to src/main/java/dev/wms/pwrapi/dao/parking/SKDParkingDAO.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import okhttp3.OkHttpClient;
2020

2121
@Repository
22-
public class ParkingDAOImpl implements ParkingDAO {
22+
public class SKDParkingDAO implements ParkingDAO {
2323

2424
public static final String PARKING_WRONSKIEGO = "Parking Wrońskiego";
2525
public static final String C_13 = "C13";

src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingArrayElement.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88

99
import lombok.AllArgsConstructor;
1010
import lombok.Data;
11+
import lombok.NoArgsConstructor;
1112
import lombok.ToString;
1213

1314

1415
@Data
1516
@ToString
1617
@AllArgsConstructor
1718
@JsonIgnoreProperties(ignoreUnknown = true)
19+
@NoArgsConstructor
1820
public class ParkingArrayElement {
1921

2022
@JsonProperty("id")

src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingResponse.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import com.fasterxml.jackson.annotation.JsonProperty;
66

77
import lombok.Data;
8+
import lombok.NoArgsConstructor;
89
import lombok.ToString;
910

1011
@ToString
1112
@Data
13+
@NoArgsConstructor
1214
public class ParkingResponse {
1315

1416
@JsonProperty("success")
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dev.wms.pwrapi.dto.parking.deserialization;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public
7+
class ParkingWithHistoryArrayElement {
8+
private String id;
9+
private String parking_id;
10+
private String czas_pomiaru;
11+
private String liczba_miejsc;
12+
private String trend;
13+
private ParkingWithHistoryChart chart;
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dev.wms.pwrapi.dto.parking.deserialization;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.Data;
5+
6+
import java.util.List;
7+
8+
@Data
9+
public class ParkingWithHistoryChart {
10+
@JsonProperty("x")
11+
private List<String> x;
12+
@JsonProperty("data")
13+
private List<String> data;
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package dev.wms.pwrapi.dto.parking.deserialization;
2+
3+
import lombok.Data;
4+
import lombok.NoArgsConstructor;
5+
6+
import java.util.List;
7+
8+
@Data
9+
@NoArgsConstructor
10+
public class ParkingWithHistoryResponse {
11+
private int success;
12+
private List<ParkingWithHistoryArrayElement> places;
13+
}

src/main/java/dev/wms/pwrapi/service/parking/ParkingProxy.java

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import dev.wms.pwrapi.dto.parking.Parking;
55
import dev.wms.pwrapi.dto.parking.ParkingWithHistory;
66
import dev.wms.pwrapi.utils.parking.ParkingDateUtils;
7-
import lombok.AllArgsConstructor;
7+
import org.springframework.beans.factory.annotation.Qualifier;
88
import org.springframework.stereotype.Component;
99

1010
import java.io.IOException;
@@ -16,23 +16,29 @@
1616
* In order to reduce stress on university servers, we use proxy design pattern so
1717
* server is called if we requested data minimum one minute before
1818
*/
19-
@AllArgsConstructor
2019
@Component
2120
public class ParkingProxy {
22-
private ParkingDAO parkingDAO;
21+
22+
private final ParkingDAO iParkingDAO;
23+
private final ParkingDAO skdParkingDAO;
2324
private List<Parking> parkingState;
2425
private List<ParkingWithHistory> parkingWithHistoryState;
2526

27+
public ParkingProxy(@Qualifier("IParkingDAO") ParkingDAO iParkingDAO, @Qualifier("SKDParkingDAO") ParkingDAO skdParkingDAO) {
28+
this.iParkingDAO = iParkingDAO;
29+
this.skdParkingDAO = skdParkingDAO;
30+
}
31+
2632
public List<Parking> getParkingState() throws IOException {
2733
if(parkingStateQualifies(parkingState)){
28-
parkingState = parkingDAO.getProcessedParkingInfo();
34+
parkingState = getProcessedParkingInfo();
2935
}
3036
return parkingState;
3137
}
3238

3339
public List<ParkingWithHistory> getParkingWithHistory() throws IOException {
3440
if(parkingStateWithHistoryQualifiesForUpdate(parkingWithHistoryState)){
35-
parkingWithHistoryState = parkingDAO.getRawParkingData();
41+
parkingWithHistoryState = getRawParkingInfo();
3642

3743
}
3844
return parkingWithHistoryState;
@@ -44,7 +50,7 @@ private boolean parkingStateQualifies(List<Parking> parkingState){
4450
}
4551

4652
private boolean parkingStateWithHistoryQualifiesForUpdate(List<ParkingWithHistory> parkingWithHistoryState){
47-
return parkingState == null || parkingWithHistoryState.isEmpty() || parseUpdateTime(parkingWithHistoryState.get(0).getLastUpdate()).isBefore(
53+
return parkingWithHistoryState == null || parkingWithHistoryState.isEmpty() || parseUpdateTime(parkingWithHistoryState.get(0).getLastUpdate()).isBefore(
4854
ParkingDateUtils.getDateTimeInPoland().minusMinutes(1)
4955
);
5056
}
@@ -53,4 +59,36 @@ private LocalDateTime parseUpdateTime(String lastUpdate){
5359
return LocalDateTime.parse(lastUpdate, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
5460
}
5561

62+
private List<Parking> getProcessedParkingInfo(){
63+
try{
64+
return iParkingDAO.getProcessedParkingInfo();
65+
} catch (Throwable t) {
66+
return getSkdProcessedParkingInfo();
67+
}
68+
}
69+
70+
private List<ParkingWithHistory> getRawParkingInfo(){
71+
try{
72+
return iParkingDAO.getRawParkingData();
73+
} catch (Throwable t){
74+
return getSkdRawParkingInfo();
75+
}
76+
}
77+
78+
private List<ParkingWithHistory> getSkdRawParkingInfo(){
79+
try {
80+
return skdParkingDAO.getRawParkingData();
81+
} catch (IOException e) {
82+
throw new RuntimeException(e);
83+
}
84+
}
85+
86+
private List<Parking> getSkdProcessedParkingInfo(){
87+
try {
88+
return skdParkingDAO.getProcessedParkingInfo();
89+
} catch (IOException e) {
90+
throw new RuntimeException(e);
91+
}
92+
}
93+
5694
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package dev.wms.pwrapi.utils.parking;
2+
3+
public class ParkingGeneralUtils {
4+
5+
/**
6+
* Determines parking based on ID in JSON response from parking server. Returns "Unknown Id" on unknown id
7+
* @param id ID from JSON response
8+
* @return Name of Parking
9+
*/
10+
public static String determineParking(String id){
11+
12+
switch (id) {
13+
case "5" -> {
14+
return "D20";
15+
}
16+
case "4" -> {
17+
return "Parking Wrońskiego";
18+
}
19+
case "2" -> {
20+
return "C13";
21+
}
22+
case "6" -> {
23+
return "Geocentrum";
24+
}
25+
case "7" -> {
26+
return "Architektura";
27+
}
28+
}
29+
30+
return "Unknown parking id: " + id;
31+
32+
}
33+
34+
}

src/test/java/dev/wms/pwrapi/parking/ParkingDAOTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515
public class ParkingDAOTest {
1616

1717
@Autowired
18-
private ParkingDAO parkingDAO;
18+
private ParkingDAO SKDParkingDAO;
1919

2020
/**
2121
* Because of migration to SKD service, trend feature is no longer supported, and trend should be equal
2222
* to zero
2323
* @throws IOException
2424
*/
2525
@Test
26-
public void trendShouldAlwaysBeZero() throws IOException {
27-
List<Parking> result = parkingDAO.getProcessedParkingInfo();
26+
public void trendShouldAlwaysBeZeroFOr() throws IOException {
27+
List<Parking> result = SKDParkingDAO.getProcessedParkingInfo();
2828
for(Parking parking : result){
2929
assertEquals(0, parking.getTrend());
3030
}

0 commit comments

Comments
 (0)